| // SPDX-License-Identifier: GPL-2.0-only |
| /* |
| * linux/arch/unicore32/kernel/puv3-nb0916.c |
| * |
| * Code specific to PKUnity SoC and UniCore ISA |
| * |
| * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn> |
| * Copyright (C) 2001-2010 Guan Xuetao |
| */ |
| |
| #include <linux/init.h> |
| #include <linux/device.h> |
| #include <linux/platform_device.h> |
| #include <linux/mtd/physmap.h> |
| #include <linux/io.h> |
| #include <linux/reboot.h> |
| #include <linux/interrupt.h> |
| #include <linux/i2c.h> |
| #include <linux/pwm.h> |
| #include <linux/pwm_backlight.h> |
| #include <linux/gpio.h> |
| #include <linux/gpio_keys.h> |
| #include <linux/input.h> |
| |
| #include <mach/hardware.h> |
| |
| static struct physmap_flash_data physmap_flash_data = { |
| .width = 1, |
| }; |
| |
| static struct resource physmap_flash_resource = { |
| .start = 0xFFF80000, |
| .end = 0xFFFFFFFF, |
| .flags = IORESOURCE_MEM, |
| }; |
| |
| static struct resource puv3_i2c_resources[] = { |
| [0] = { |
| .start = io_v2p(PKUNITY_I2C_BASE), |
| .end = io_v2p(PKUNITY_I2C_BASE) + 0xff, |
| .flags = IORESOURCE_MEM, |
| }, |
| [1] = { |
| .start = IRQ_I2C, |
| .end = IRQ_I2C, |
| .flags = IORESOURCE_IRQ, |
| } |
| }; |
| |
| static struct pwm_lookup nb0916_pwm_lookup[] = { |
| PWM_LOOKUP("PKUnity-v3-PWM", 0, "pwm-backlight", NULL, 70 * 1024, |
| PWM_POLARITY_NORMAL), |
| }; |
| |
| static struct platform_pwm_backlight_data nb0916_backlight_data = { |
| .max_brightness = 100, |
| .dft_brightness = 100, |
| }; |
| |
| static struct gpio_keys_button nb0916_gpio_keys[] = { |
| { |
| .type = EV_KEY, |
| .code = KEY_POWER, |
| .gpio = GPI_SOFF_REQ, |
| .desc = "Power Button", |
| .wakeup = 1, |
| .active_low = 1, |
| }, |
| { |
| .type = EV_KEY, |
| .code = BTN_TOUCH, |
| .gpio = GPI_BTN_TOUCH, |
| .desc = "Touchpad Button", |
| .wakeup = 1, |
| .active_low = 1, |
| }, |
| }; |
| |
| static struct gpio_keys_platform_data nb0916_gpio_button_data = { |
| .buttons = nb0916_gpio_keys, |
| .nbuttons = ARRAY_SIZE(nb0916_gpio_keys), |
| }; |
| |
| static irqreturn_t nb0916_lcdcaseoff_handler(int irq, void *dev_id) |
| { |
| if (gpio_get_value(GPI_LCD_CASE_OFF)) |
| gpio_set_value(GPO_LCD_EN, 1); |
| else |
| gpio_set_value(GPO_LCD_EN, 0); |
| |
| return IRQ_HANDLED; |
| } |
| |
| static irqreturn_t nb0916_overheat_handler(int irq, void *dev_id) |
| { |
| machine_halt(); |
| /* SYSTEM HALT, NO RETURN */ |
| return IRQ_HANDLED; |
| } |
| |
| static struct i2c_board_info __initdata puv3_i2c_devices[] = { |
| { I2C_BOARD_INFO("lm75", I2C_TAR_THERMAL), }, |
| { I2C_BOARD_INFO("bq27200", I2C_TAR_PWIC), }, |
| { I2C_BOARD_INFO("24c02", I2C_TAR_EEPROM), }, |
| }; |
| |
| int __init mach_nb0916_init(void) |
| { |
| i2c_register_board_info(0, puv3_i2c_devices, |
| ARRAY_SIZE(puv3_i2c_devices)); |
| |
| platform_device_register_simple("PKUnity-v3-I2C", -1, |
| puv3_i2c_resources, ARRAY_SIZE(puv3_i2c_resources)); |
| |
| pwm_add_table(nb0916_pwm_lookup, ARRAY_SIZE(nb0916_pwm_lookup)); |
| |
| platform_device_register_data(NULL, "pwm-backlight", -1, |
| &nb0916_backlight_data, sizeof(nb0916_backlight_data)); |
| |
| platform_device_register_data(NULL, "gpio-keys", -1, |
| &nb0916_gpio_button_data, sizeof(nb0916_gpio_button_data)); |
| |
| platform_device_register_resndata(NULL, "physmap-flash", -1, |
| &physmap_flash_resource, 1, |
| &physmap_flash_data, sizeof(physmap_flash_data)); |
| |
| if (request_irq(gpio_to_irq(GPI_LCD_CASE_OFF), |
| &nb0916_lcdcaseoff_handler, |
| IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, |
| "NB0916 lcd case off", NULL) < 0) { |
| |
| printk(KERN_DEBUG "LCD-Case-OFF IRQ %d not available\n", |
| gpio_to_irq(GPI_LCD_CASE_OFF)); |
| } |
| |
| if (request_irq(gpio_to_irq(GPI_OTP_INT), &nb0916_overheat_handler, |
| IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, |
| "NB0916 overheating protection", NULL) < 0) { |
| |
| printk(KERN_DEBUG "Overheating Protection IRQ %d not available\n", |
| gpio_to_irq(GPI_OTP_INT)); |
| } |
| |
| return 0; |
| } |
| |
| subsys_initcall_sync(mach_nb0916_init); |