|
@@ -417,3 +417,84 @@ static void cpld_led_set(struct led_classdev *cdev, enum led_brightness b)
|
|
struct cpld_led *led = container_of(cdev, struct cpld_led, cdev);
|
|
struct cpld_led *led = container_of(cdev, struct cpld_led, cdev);
|
|
u8 reg = __raw_readb(cpld + CPLD_LEDS);
|
|
u8 reg = __raw_readb(cpld + CPLD_LEDS);
|
|
|
|
|
|
|
|
+ if (b != LED_OFF)
|
|
|
|
+ reg &= ~led->mask;
|
|
|
|
+ else
|
|
|
|
+ reg |= led->mask;
|
|
|
|
+ __raw_writeb(reg, cpld + CPLD_LEDS);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static enum led_brightness cpld_led_get(struct led_classdev *cdev)
|
|
|
|
+{
|
|
|
|
+ struct cpld_led *led = container_of(cdev, struct cpld_led, cdev);
|
|
|
|
+ u8 reg = __raw_readb(cpld + CPLD_LEDS);
|
|
|
|
+
|
|
|
|
+ return (reg & led->mask) ? LED_OFF : LED_FULL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int __init cpld_leds_init(void)
|
|
|
|
+{
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ if (!have_leds() || !cpld)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ /* setup LEDs */
|
|
|
|
+ __raw_writeb(0xff, cpld + CPLD_LEDS);
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(cpld_leds); i++) {
|
|
|
|
+ struct cpld_led *led;
|
|
|
|
+
|
|
|
|
+ led = kzalloc(sizeof(*led), GFP_KERNEL);
|
|
|
|
+ if (!led)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ led->cdev.name = cpld_leds[i].name;
|
|
|
|
+ led->cdev.brightness_set = cpld_led_set;
|
|
|
|
+ led->cdev.brightness_get = cpld_led_get;
|
|
|
|
+ led->cdev.default_trigger = cpld_leds[i].trigger;
|
|
|
|
+ led->mask = BIT(i);
|
|
|
|
+
|
|
|
|
+ if (led_classdev_register(NULL, &led->cdev) < 0) {
|
|
|
|
+ kfree(led);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+/* run after subsys_initcall() for LEDs */
|
|
|
|
+fs_initcall(cpld_leds_init);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static void __init evm_init_cpld(void)
|
|
|
|
+{
|
|
|
|
+ u8 mux, resets;
|
|
|
|
+ const char *label;
|
|
|
|
+ struct clk *aemif_clk;
|
|
|
|
+
|
|
|
|
+ /* Make sure we can configure the CPLD through CS1. Then
|
|
|
|
+ * leave it on for later access to MMC and LED registers.
|
|
|
|
+ */
|
|
|
|
+ aemif_clk = clk_get(NULL, "aemif");
|
|
|
|
+ if (IS_ERR(aemif_clk))
|
|
|
|
+ return;
|
|
|
|
+ clk_prepare_enable(aemif_clk);
|
|
|
|
+
|
|
|
|
+ if (request_mem_region(DM365_ASYNC_EMIF_DATA_CE1_BASE, SECTION_SIZE,
|
|
|
|
+ "cpld") == NULL)
|
|
|
|
+ goto fail;
|
|
|
|
+ cpld = ioremap(DM365_ASYNC_EMIF_DATA_CE1_BASE, SECTION_SIZE);
|
|
|
|
+ if (!cpld) {
|
|
|
|
+ release_mem_region(DM365_ASYNC_EMIF_DATA_CE1_BASE,
|
|
|
|
+ SECTION_SIZE);
|
|
|
|
+fail:
|
|
|
|
+ pr_err("ERROR: can't map CPLD\n");
|
|
|
|
+ clk_disable_unprepare(aemif_clk);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* External muxing for some signals */
|
|
|
|
+ mux = 0;
|
|
|
|
+
|
|
|
|
+ /* Read SW5 to set up NAND + keypad _or_ OneNAND (sync read).
|
|
|
|
+ * NOTE: SW4 bus width setting must match!
|