1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * arch/arm/mach-ep93xx/core.c |
4 | * Core routines for Cirrus EP93xx chips. |
5 | * |
6 | * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> |
7 | * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org> |
8 | * |
9 | * Thanks go to Michael Burian and Ray Lehtiniemi for their key |
10 | * role in the ep93xx linux community. |
11 | */ |
12 | |
13 | #define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt |
14 | |
15 | #include <linux/kernel.h> |
16 | #include <linux/init.h> |
17 | #include <linux/platform_device.h> |
18 | #include <linux/interrupt.h> |
19 | #include <linux/dma-mapping.h> |
20 | #include <linux/sys_soc.h> |
21 | #include <linux/irq.h> |
22 | #include <linux/io.h> |
23 | #include <linux/gpio.h> |
24 | #include <linux/leds.h> |
25 | #include <linux/uaccess.h> |
26 | #include <linux/termios.h> |
27 | #include <linux/amba/bus.h> |
28 | #include <linux/amba/serial.h> |
29 | #include <linux/mtd/physmap.h> |
30 | #include <linux/i2c.h> |
31 | #include <linux/gpio/machine.h> |
32 | #include <linux/spi/spi.h> |
33 | #include <linux/export.h> |
34 | #include <linux/irqchip/arm-vic.h> |
35 | #include <linux/reboot.h> |
36 | #include <linux/usb/ohci_pdriver.h> |
37 | #include <linux/random.h> |
38 | |
39 | #include "hardware.h" |
40 | #include <linux/platform_data/video-ep93xx.h> |
41 | #include <linux/platform_data/keypad-ep93xx.h> |
42 | #include <linux/platform_data/spi-ep93xx.h> |
43 | #include <linux/soc/cirrus/ep93xx.h> |
44 | |
45 | #include "gpio-ep93xx.h" |
46 | |
47 | #include <asm/mach/arch.h> |
48 | #include <asm/mach/map.h> |
49 | |
50 | #include "soc.h" |
51 | #include "irqs.h" |
52 | |
53 | /************************************************************************* |
54 | * Static I/O mappings that are needed for all EP93xx platforms |
55 | *************************************************************************/ |
56 | static struct map_desc ep93xx_io_desc[] __initdata = { |
57 | { |
58 | .virtual = EP93XX_AHB_VIRT_BASE, |
59 | .pfn = __phys_to_pfn(EP93XX_AHB_PHYS_BASE), |
60 | .length = EP93XX_AHB_SIZE, |
61 | .type = MT_DEVICE, |
62 | }, { |
63 | .virtual = EP93XX_APB_VIRT_BASE, |
64 | .pfn = __phys_to_pfn(EP93XX_APB_PHYS_BASE), |
65 | .length = EP93XX_APB_SIZE, |
66 | .type = MT_DEVICE, |
67 | }, |
68 | }; |
69 | |
70 | void __init ep93xx_map_io(void) |
71 | { |
72 | iotable_init(ep93xx_io_desc, ARRAY_SIZE(ep93xx_io_desc)); |
73 | } |
74 | |
75 | /************************************************************************* |
76 | * EP93xx IRQ handling |
77 | *************************************************************************/ |
78 | void __init ep93xx_init_irq(void) |
79 | { |
80 | vic_init(EP93XX_VIC1_BASE, IRQ_EP93XX_VIC0, EP93XX_VIC1_VALID_IRQ_MASK, resume_sources: 0); |
81 | vic_init(EP93XX_VIC2_BASE, IRQ_EP93XX_VIC1, EP93XX_VIC2_VALID_IRQ_MASK, resume_sources: 0); |
82 | } |
83 | |
84 | |
85 | /************************************************************************* |
86 | * EP93xx System Controller Software Locked register handling |
87 | *************************************************************************/ |
88 | |
89 | /* |
90 | * syscon_swlock prevents anything else from writing to the syscon |
91 | * block while a software locked register is being written. |
92 | */ |
93 | static DEFINE_SPINLOCK(syscon_swlock); |
94 | |
95 | void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg) |
96 | { |
97 | unsigned long flags; |
98 | |
99 | spin_lock_irqsave(&syscon_swlock, flags); |
100 | |
101 | __raw_writel(val: 0xaa, EP93XX_SYSCON_SWLOCK); |
102 | __raw_writel(val, addr: reg); |
103 | |
104 | spin_unlock_irqrestore(lock: &syscon_swlock, flags); |
105 | } |
106 | |
107 | void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits) |
108 | { |
109 | unsigned long flags; |
110 | unsigned int val; |
111 | |
112 | spin_lock_irqsave(&syscon_swlock, flags); |
113 | |
114 | val = __raw_readl(EP93XX_SYSCON_DEVCFG); |
115 | val &= ~clear_bits; |
116 | val |= set_bits; |
117 | __raw_writel(val: 0xaa, EP93XX_SYSCON_SWLOCK); |
118 | __raw_writel(val, EP93XX_SYSCON_DEVCFG); |
119 | |
120 | spin_unlock_irqrestore(lock: &syscon_swlock, flags); |
121 | } |
122 | |
123 | /** |
124 | * ep93xx_chip_revision() - returns the EP93xx chip revision |
125 | * |
126 | * See "platform.h" for more information. |
127 | */ |
128 | unsigned int ep93xx_chip_revision(void) |
129 | { |
130 | unsigned int v; |
131 | |
132 | v = __raw_readl(EP93XX_SYSCON_SYSCFG); |
133 | v &= EP93XX_SYSCON_SYSCFG_REV_MASK; |
134 | v >>= EP93XX_SYSCON_SYSCFG_REV_SHIFT; |
135 | return v; |
136 | } |
137 | EXPORT_SYMBOL_GPL(ep93xx_chip_revision); |
138 | |
139 | /************************************************************************* |
140 | * EP93xx GPIO |
141 | *************************************************************************/ |
142 | static struct resource ep93xx_gpio_resource[] = { |
143 | DEFINE_RES_MEM(EP93XX_GPIO_PHYS_BASE, 0xcc), |
144 | DEFINE_RES_IRQ(IRQ_EP93XX_GPIO_AB), |
145 | DEFINE_RES_IRQ(IRQ_EP93XX_GPIO0MUX), |
146 | DEFINE_RES_IRQ(IRQ_EP93XX_GPIO1MUX), |
147 | DEFINE_RES_IRQ(IRQ_EP93XX_GPIO2MUX), |
148 | DEFINE_RES_IRQ(IRQ_EP93XX_GPIO3MUX), |
149 | DEFINE_RES_IRQ(IRQ_EP93XX_GPIO4MUX), |
150 | DEFINE_RES_IRQ(IRQ_EP93XX_GPIO5MUX), |
151 | DEFINE_RES_IRQ(IRQ_EP93XX_GPIO6MUX), |
152 | DEFINE_RES_IRQ(IRQ_EP93XX_GPIO7MUX), |
153 | }; |
154 | |
155 | static struct platform_device ep93xx_gpio_device = { |
156 | .name = "gpio-ep93xx" , |
157 | .id = -1, |
158 | .num_resources = ARRAY_SIZE(ep93xx_gpio_resource), |
159 | .resource = ep93xx_gpio_resource, |
160 | }; |
161 | |
162 | /************************************************************************* |
163 | * EP93xx peripheral handling |
164 | *************************************************************************/ |
165 | #define EP93XX_UART_MCR_OFFSET (0x0100) |
166 | |
167 | static void ep93xx_uart_set_mctrl(struct amba_device *dev, |
168 | void __iomem *base, unsigned int mctrl) |
169 | { |
170 | unsigned int mcr; |
171 | |
172 | mcr = 0; |
173 | if (mctrl & TIOCM_RTS) |
174 | mcr |= 2; |
175 | if (mctrl & TIOCM_DTR) |
176 | mcr |= 1; |
177 | |
178 | __raw_writel(val: mcr, addr: base + EP93XX_UART_MCR_OFFSET); |
179 | } |
180 | |
181 | static struct amba_pl010_data ep93xx_uart_data = { |
182 | .set_mctrl = ep93xx_uart_set_mctrl, |
183 | }; |
184 | |
185 | static AMBA_APB_DEVICE(uart1, "apb:uart1" , 0x00041010, EP93XX_UART1_PHYS_BASE, |
186 | { IRQ_EP93XX_UART1 }, &ep93xx_uart_data); |
187 | |
188 | static AMBA_APB_DEVICE(uart2, "apb:uart2" , 0x00041010, EP93XX_UART2_PHYS_BASE, |
189 | { IRQ_EP93XX_UART2 }, NULL); |
190 | |
191 | static AMBA_APB_DEVICE(uart3, "apb:uart3" , 0x00041010, EP93XX_UART3_PHYS_BASE, |
192 | { IRQ_EP93XX_UART3 }, &ep93xx_uart_data); |
193 | |
194 | static struct resource ep93xx_rtc_resource[] = { |
195 | DEFINE_RES_MEM(EP93XX_RTC_PHYS_BASE, 0x10c), |
196 | }; |
197 | |
198 | static struct platform_device ep93xx_rtc_device = { |
199 | .name = "ep93xx-rtc" , |
200 | .id = -1, |
201 | .num_resources = ARRAY_SIZE(ep93xx_rtc_resource), |
202 | .resource = ep93xx_rtc_resource, |
203 | }; |
204 | |
205 | /************************************************************************* |
206 | * EP93xx OHCI USB Host |
207 | *************************************************************************/ |
208 | |
209 | static struct clk *ep93xx_ohci_host_clock; |
210 | |
211 | static int ep93xx_ohci_power_on(struct platform_device *pdev) |
212 | { |
213 | if (!ep93xx_ohci_host_clock) { |
214 | ep93xx_ohci_host_clock = devm_clk_get(dev: &pdev->dev, NULL); |
215 | if (IS_ERR(ptr: ep93xx_ohci_host_clock)) |
216 | return PTR_ERR(ptr: ep93xx_ohci_host_clock); |
217 | } |
218 | |
219 | return clk_prepare_enable(clk: ep93xx_ohci_host_clock); |
220 | } |
221 | |
222 | static void ep93xx_ohci_power_off(struct platform_device *pdev) |
223 | { |
224 | clk_disable(clk: ep93xx_ohci_host_clock); |
225 | } |
226 | |
227 | static struct usb_ohci_pdata ep93xx_ohci_pdata = { |
228 | .power_on = ep93xx_ohci_power_on, |
229 | .power_off = ep93xx_ohci_power_off, |
230 | .power_suspend = ep93xx_ohci_power_off, |
231 | }; |
232 | |
233 | static struct resource ep93xx_ohci_resources[] = { |
234 | DEFINE_RES_MEM(EP93XX_USB_PHYS_BASE, 0x1000), |
235 | DEFINE_RES_IRQ(IRQ_EP93XX_USB), |
236 | }; |
237 | |
238 | static u64 ep93xx_ohci_dma_mask = DMA_BIT_MASK(32); |
239 | |
240 | static struct platform_device ep93xx_ohci_device = { |
241 | .name = "ohci-platform" , |
242 | .id = -1, |
243 | .num_resources = ARRAY_SIZE(ep93xx_ohci_resources), |
244 | .resource = ep93xx_ohci_resources, |
245 | .dev = { |
246 | .dma_mask = &ep93xx_ohci_dma_mask, |
247 | .coherent_dma_mask = DMA_BIT_MASK(32), |
248 | .platform_data = &ep93xx_ohci_pdata, |
249 | }, |
250 | }; |
251 | |
252 | /************************************************************************* |
253 | * EP93xx physmap'ed flash |
254 | *************************************************************************/ |
255 | static struct physmap_flash_data ep93xx_flash_data; |
256 | |
257 | static struct resource ep93xx_flash_resource = { |
258 | .flags = IORESOURCE_MEM, |
259 | }; |
260 | |
261 | static struct platform_device ep93xx_flash = { |
262 | .name = "physmap-flash" , |
263 | .id = 0, |
264 | .dev = { |
265 | .platform_data = &ep93xx_flash_data, |
266 | }, |
267 | .num_resources = 1, |
268 | .resource = &ep93xx_flash_resource, |
269 | }; |
270 | |
271 | /** |
272 | * ep93xx_register_flash() - Register the external flash device. |
273 | * @width: bank width in octets |
274 | * @start: resource start address |
275 | * @size: resource size |
276 | */ |
277 | void __init ep93xx_register_flash(unsigned int width, |
278 | resource_size_t start, resource_size_t size) |
279 | { |
280 | ep93xx_flash_data.width = width; |
281 | |
282 | ep93xx_flash_resource.start = start; |
283 | ep93xx_flash_resource.end = start + size - 1; |
284 | |
285 | platform_device_register(&ep93xx_flash); |
286 | } |
287 | |
288 | |
289 | /************************************************************************* |
290 | * EP93xx ethernet peripheral handling |
291 | *************************************************************************/ |
292 | static struct ep93xx_eth_data ep93xx_eth_data; |
293 | |
294 | static struct resource ep93xx_eth_resource[] = { |
295 | DEFINE_RES_MEM(EP93XX_ETHERNET_PHYS_BASE, 0x10000), |
296 | DEFINE_RES_IRQ(IRQ_EP93XX_ETHERNET), |
297 | }; |
298 | |
299 | static u64 ep93xx_eth_dma_mask = DMA_BIT_MASK(32); |
300 | |
301 | static struct platform_device ep93xx_eth_device = { |
302 | .name = "ep93xx-eth" , |
303 | .id = -1, |
304 | .dev = { |
305 | .platform_data = &ep93xx_eth_data, |
306 | .coherent_dma_mask = DMA_BIT_MASK(32), |
307 | .dma_mask = &ep93xx_eth_dma_mask, |
308 | }, |
309 | .num_resources = ARRAY_SIZE(ep93xx_eth_resource), |
310 | .resource = ep93xx_eth_resource, |
311 | }; |
312 | |
313 | /** |
314 | * ep93xx_register_eth - Register the built-in ethernet platform device. |
315 | * @data: platform specific ethernet configuration (__initdata) |
316 | * @copy_addr: flag indicating that the MAC address should be copied |
317 | * from the IndAd registers (as programmed by the bootloader) |
318 | */ |
319 | void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr) |
320 | { |
321 | if (copy_addr) |
322 | memcpy_fromio(data->dev_addr, EP93XX_ETHERNET_BASE + 0x50, 6); |
323 | |
324 | ep93xx_eth_data = *data; |
325 | platform_device_register(&ep93xx_eth_device); |
326 | } |
327 | |
328 | |
329 | /************************************************************************* |
330 | * EP93xx i2c peripheral handling |
331 | *************************************************************************/ |
332 | |
333 | /* All EP93xx devices use the same two GPIO pins for I2C bit-banging */ |
334 | static struct gpiod_lookup_table ep93xx_i2c_gpiod_table = { |
335 | .dev_id = "i2c-gpio.0" , |
336 | .table = { |
337 | /* Use local offsets on gpiochip/port "G" */ |
338 | GPIO_LOOKUP_IDX("G" , 1, NULL, 0, |
339 | GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN), |
340 | GPIO_LOOKUP_IDX("G" , 0, NULL, 1, |
341 | GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN), |
342 | { } |
343 | }, |
344 | }; |
345 | |
346 | static struct platform_device ep93xx_i2c_device = { |
347 | .name = "i2c-gpio" , |
348 | .id = 0, |
349 | .dev = { |
350 | .platform_data = NULL, |
351 | }, |
352 | }; |
353 | |
354 | /** |
355 | * ep93xx_register_i2c - Register the i2c platform device. |
356 | * @devices: platform specific i2c bus device information (__initdata) |
357 | * @num: the number of devices on the i2c bus |
358 | */ |
359 | void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num) |
360 | { |
361 | /* |
362 | * FIXME: this just sets the two pins as non-opendrain, as no |
363 | * platforms tries to do that anyway. Flag the applicable lines |
364 | * as open drain in the GPIO_LOOKUP above and the driver or |
365 | * gpiolib will handle open drain/open drain emulation as need |
366 | * be. Right now i2c-gpio emulates open drain which is not |
367 | * optimal. |
368 | */ |
369 | __raw_writel(val: (0 << 1) | (0 << 0), |
370 | EP93XX_GPIO_EEDRIVE); |
371 | |
372 | i2c_register_board_info(busnum: 0, info: devices, n: num); |
373 | gpiod_add_lookup_table(table: &ep93xx_i2c_gpiod_table); |
374 | platform_device_register(&ep93xx_i2c_device); |
375 | } |
376 | |
377 | /************************************************************************* |
378 | * EP93xx SPI peripheral handling |
379 | *************************************************************************/ |
380 | static struct ep93xx_spi_info ep93xx_spi_master_data; |
381 | |
382 | static struct resource ep93xx_spi_resources[] = { |
383 | DEFINE_RES_MEM(EP93XX_SPI_PHYS_BASE, 0x18), |
384 | DEFINE_RES_IRQ(IRQ_EP93XX_SSP), |
385 | }; |
386 | |
387 | static u64 ep93xx_spi_dma_mask = DMA_BIT_MASK(32); |
388 | |
389 | static struct platform_device ep93xx_spi_device = { |
390 | .name = "ep93xx-spi" , |
391 | .id = 0, |
392 | .dev = { |
393 | .platform_data = &ep93xx_spi_master_data, |
394 | .coherent_dma_mask = DMA_BIT_MASK(32), |
395 | .dma_mask = &ep93xx_spi_dma_mask, |
396 | }, |
397 | .num_resources = ARRAY_SIZE(ep93xx_spi_resources), |
398 | .resource = ep93xx_spi_resources, |
399 | }; |
400 | |
401 | /** |
402 | * ep93xx_register_spi() - registers spi platform device |
403 | * @info: ep93xx board specific spi master info (__initdata) |
404 | * @devices: SPI devices to register (__initdata) |
405 | * @num: number of SPI devices to register |
406 | * |
407 | * This function registers platform device for the EP93xx SPI controller and |
408 | * also makes sure that SPI pins are muxed so that I2S is not using those pins. |
409 | */ |
410 | void __init ep93xx_register_spi(struct ep93xx_spi_info *info, |
411 | struct spi_board_info *devices, int num) |
412 | { |
413 | /* |
414 | * When SPI is used, we need to make sure that I2S is muxed off from |
415 | * SPI pins. |
416 | */ |
417 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2SONSSP); |
418 | |
419 | ep93xx_spi_master_data = *info; |
420 | spi_register_board_info(info: devices, n: num); |
421 | platform_device_register(&ep93xx_spi_device); |
422 | } |
423 | |
424 | /************************************************************************* |
425 | * EP93xx LEDs |
426 | *************************************************************************/ |
427 | static const struct gpio_led ep93xx_led_pins[] __initconst = { |
428 | { |
429 | .name = "platform:grled" , |
430 | }, { |
431 | .name = "platform:rdled" , |
432 | }, |
433 | }; |
434 | |
435 | static const struct gpio_led_platform_data ep93xx_led_data __initconst = { |
436 | .num_leds = ARRAY_SIZE(ep93xx_led_pins), |
437 | .leds = ep93xx_led_pins, |
438 | }; |
439 | |
440 | static struct gpiod_lookup_table ep93xx_leds_gpio_table = { |
441 | .dev_id = "leds-gpio" , |
442 | .table = { |
443 | /* Use local offsets on gpiochip/port "E" */ |
444 | GPIO_LOOKUP_IDX("E" , 0, NULL, 0, GPIO_ACTIVE_HIGH), |
445 | GPIO_LOOKUP_IDX("E" , 1, NULL, 1, GPIO_ACTIVE_HIGH), |
446 | { } |
447 | }, |
448 | }; |
449 | |
450 | /************************************************************************* |
451 | * EP93xx pwm peripheral handling |
452 | *************************************************************************/ |
453 | static struct resource ep93xx_pwm0_resource[] = { |
454 | DEFINE_RES_MEM(EP93XX_PWM_PHYS_BASE, 0x10), |
455 | }; |
456 | |
457 | static struct platform_device ep93xx_pwm0_device = { |
458 | .name = "ep93xx-pwm" , |
459 | .id = 0, |
460 | .num_resources = ARRAY_SIZE(ep93xx_pwm0_resource), |
461 | .resource = ep93xx_pwm0_resource, |
462 | }; |
463 | |
464 | static struct resource ep93xx_pwm1_resource[] = { |
465 | DEFINE_RES_MEM(EP93XX_PWM_PHYS_BASE + 0x20, 0x10), |
466 | }; |
467 | |
468 | static struct platform_device ep93xx_pwm1_device = { |
469 | .name = "ep93xx-pwm" , |
470 | .id = 1, |
471 | .num_resources = ARRAY_SIZE(ep93xx_pwm1_resource), |
472 | .resource = ep93xx_pwm1_resource, |
473 | }; |
474 | |
475 | void __init ep93xx_register_pwm(int pwm0, int pwm1) |
476 | { |
477 | if (pwm0) |
478 | platform_device_register(&ep93xx_pwm0_device); |
479 | |
480 | /* NOTE: EP9307 does not have PWMOUT1 (pin EGPIO14) */ |
481 | if (pwm1) |
482 | platform_device_register(&ep93xx_pwm1_device); |
483 | } |
484 | |
485 | int ep93xx_pwm_acquire_gpio(struct platform_device *pdev) |
486 | { |
487 | int err; |
488 | |
489 | if (pdev->id == 0) { |
490 | err = 0; |
491 | } else if (pdev->id == 1) { |
492 | err = gpio_request(EP93XX_GPIO_LINE_EGPIO14, |
493 | label: dev_name(dev: &pdev->dev)); |
494 | if (err) |
495 | return err; |
496 | err = gpio_direction_output(EP93XX_GPIO_LINE_EGPIO14, value: 0); |
497 | if (err) |
498 | goto fail; |
499 | |
500 | /* PWM 1 output on EGPIO[14] */ |
501 | ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_PONG); |
502 | } else { |
503 | err = -ENODEV; |
504 | } |
505 | |
506 | return err; |
507 | |
508 | fail: |
509 | gpio_free(EP93XX_GPIO_LINE_EGPIO14); |
510 | return err; |
511 | } |
512 | EXPORT_SYMBOL(ep93xx_pwm_acquire_gpio); |
513 | |
514 | void ep93xx_pwm_release_gpio(struct platform_device *pdev) |
515 | { |
516 | if (pdev->id == 1) { |
517 | gpio_direction_input(EP93XX_GPIO_LINE_EGPIO14); |
518 | gpio_free(EP93XX_GPIO_LINE_EGPIO14); |
519 | |
520 | /* EGPIO[14] used for GPIO */ |
521 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_PONG); |
522 | } |
523 | } |
524 | EXPORT_SYMBOL(ep93xx_pwm_release_gpio); |
525 | |
526 | |
527 | /************************************************************************* |
528 | * EP93xx video peripheral handling |
529 | *************************************************************************/ |
530 | static struct ep93xxfb_mach_info ep93xxfb_data; |
531 | |
532 | static struct resource ep93xx_fb_resource[] = { |
533 | DEFINE_RES_MEM(EP93XX_RASTER_PHYS_BASE, 0x800), |
534 | }; |
535 | |
536 | static struct platform_device ep93xx_fb_device = { |
537 | .name = "ep93xx-fb" , |
538 | .id = -1, |
539 | .dev = { |
540 | .platform_data = &ep93xxfb_data, |
541 | .coherent_dma_mask = DMA_BIT_MASK(32), |
542 | .dma_mask = &ep93xx_fb_device.dev.coherent_dma_mask, |
543 | }, |
544 | .num_resources = ARRAY_SIZE(ep93xx_fb_resource), |
545 | .resource = ep93xx_fb_resource, |
546 | }; |
547 | |
548 | /* The backlight use a single register in the framebuffer's register space */ |
549 | #define EP93XX_RASTER_REG_BRIGHTNESS 0x20 |
550 | |
551 | static struct resource ep93xx_bl_resources[] = { |
552 | DEFINE_RES_MEM(EP93XX_RASTER_PHYS_BASE + |
553 | EP93XX_RASTER_REG_BRIGHTNESS, 0x04), |
554 | }; |
555 | |
556 | static struct platform_device ep93xx_bl_device = { |
557 | .name = "ep93xx-bl" , |
558 | .id = -1, |
559 | .num_resources = ARRAY_SIZE(ep93xx_bl_resources), |
560 | .resource = ep93xx_bl_resources, |
561 | }; |
562 | |
563 | /** |
564 | * ep93xx_register_fb - Register the framebuffer platform device. |
565 | * @data: platform specific framebuffer configuration (__initdata) |
566 | */ |
567 | void __init ep93xx_register_fb(struct ep93xxfb_mach_info *data) |
568 | { |
569 | ep93xxfb_data = *data; |
570 | platform_device_register(&ep93xx_fb_device); |
571 | platform_device_register(&ep93xx_bl_device); |
572 | } |
573 | |
574 | |
575 | /************************************************************************* |
576 | * EP93xx matrix keypad peripheral handling |
577 | *************************************************************************/ |
578 | static struct ep93xx_keypad_platform_data ep93xx_keypad_data; |
579 | |
580 | static struct resource ep93xx_keypad_resource[] = { |
581 | DEFINE_RES_MEM(EP93XX_KEY_MATRIX_PHYS_BASE, 0x0c), |
582 | DEFINE_RES_IRQ(IRQ_EP93XX_KEY), |
583 | }; |
584 | |
585 | static struct platform_device ep93xx_keypad_device = { |
586 | .name = "ep93xx-keypad" , |
587 | .id = -1, |
588 | .dev = { |
589 | .platform_data = &ep93xx_keypad_data, |
590 | }, |
591 | .num_resources = ARRAY_SIZE(ep93xx_keypad_resource), |
592 | .resource = ep93xx_keypad_resource, |
593 | }; |
594 | |
595 | /** |
596 | * ep93xx_register_keypad - Register the keypad platform device. |
597 | * @data: platform specific keypad configuration (__initdata) |
598 | */ |
599 | void __init ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data) |
600 | { |
601 | ep93xx_keypad_data = *data; |
602 | platform_device_register(&ep93xx_keypad_device); |
603 | } |
604 | |
605 | int ep93xx_keypad_acquire_gpio(struct platform_device *pdev) |
606 | { |
607 | int err; |
608 | int i; |
609 | |
610 | for (i = 0; i < 8; i++) { |
611 | err = gpio_request(EP93XX_GPIO_LINE_C(i), label: dev_name(dev: &pdev->dev)); |
612 | if (err) |
613 | goto fail_gpio_c; |
614 | err = gpio_request(EP93XX_GPIO_LINE_D(i), label: dev_name(dev: &pdev->dev)); |
615 | if (err) |
616 | goto fail_gpio_d; |
617 | } |
618 | |
619 | /* Enable the keypad controller; GPIO ports C and D used for keypad */ |
620 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_KEYS | |
621 | EP93XX_SYSCON_DEVCFG_GONK); |
622 | |
623 | return 0; |
624 | |
625 | fail_gpio_d: |
626 | gpio_free(EP93XX_GPIO_LINE_C(i)); |
627 | fail_gpio_c: |
628 | for (--i; i >= 0; --i) { |
629 | gpio_free(EP93XX_GPIO_LINE_C(i)); |
630 | gpio_free(EP93XX_GPIO_LINE_D(i)); |
631 | } |
632 | return err; |
633 | } |
634 | EXPORT_SYMBOL(ep93xx_keypad_acquire_gpio); |
635 | |
636 | void ep93xx_keypad_release_gpio(struct platform_device *pdev) |
637 | { |
638 | int i; |
639 | |
640 | for (i = 0; i < 8; i++) { |
641 | gpio_free(EP93XX_GPIO_LINE_C(i)); |
642 | gpio_free(EP93XX_GPIO_LINE_D(i)); |
643 | } |
644 | |
645 | /* Disable the keypad controller; GPIO ports C and D used for GPIO */ |
646 | ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS | |
647 | EP93XX_SYSCON_DEVCFG_GONK); |
648 | } |
649 | EXPORT_SYMBOL(ep93xx_keypad_release_gpio); |
650 | |
651 | /************************************************************************* |
652 | * EP93xx I2S audio peripheral handling |
653 | *************************************************************************/ |
654 | static struct resource ep93xx_i2s_resource[] = { |
655 | DEFINE_RES_MEM(EP93XX_I2S_PHYS_BASE, 0x100), |
656 | DEFINE_RES_IRQ(IRQ_EP93XX_SAI), |
657 | }; |
658 | |
659 | static struct platform_device ep93xx_i2s_device = { |
660 | .name = "ep93xx-i2s" , |
661 | .id = -1, |
662 | .num_resources = ARRAY_SIZE(ep93xx_i2s_resource), |
663 | .resource = ep93xx_i2s_resource, |
664 | }; |
665 | |
666 | static struct platform_device ep93xx_pcm_device = { |
667 | .name = "ep93xx-pcm-audio" , |
668 | .id = -1, |
669 | }; |
670 | |
671 | void __init ep93xx_register_i2s(void) |
672 | { |
673 | platform_device_register(&ep93xx_i2s_device); |
674 | platform_device_register(&ep93xx_pcm_device); |
675 | } |
676 | |
677 | #define EP93XX_SYSCON_DEVCFG_I2S_MASK (EP93XX_SYSCON_DEVCFG_I2SONSSP | \ |
678 | EP93XX_SYSCON_DEVCFG_I2SONAC97) |
679 | |
680 | #define EP93XX_I2SCLKDIV_MASK (EP93XX_SYSCON_I2SCLKDIV_ORIDE | \ |
681 | EP93XX_SYSCON_I2SCLKDIV_SPOL) |
682 | |
683 | int ep93xx_i2s_acquire(void) |
684 | { |
685 | unsigned val; |
686 | |
687 | ep93xx_devcfg_set_clear(EP93XX_SYSCON_DEVCFG_I2SONAC97, |
688 | EP93XX_SYSCON_DEVCFG_I2S_MASK); |
689 | |
690 | /* |
691 | * This is potentially racy with the clock api for i2s_mclk, sclk and |
692 | * lrclk. Since the i2s driver is the only user of those clocks we |
693 | * rely on it to prevent parallel use of this function and the |
694 | * clock api for the i2s clocks. |
695 | */ |
696 | val = __raw_readl(EP93XX_SYSCON_I2SCLKDIV); |
697 | val &= ~EP93XX_I2SCLKDIV_MASK; |
698 | val |= EP93XX_SYSCON_I2SCLKDIV_ORIDE | EP93XX_SYSCON_I2SCLKDIV_SPOL; |
699 | ep93xx_syscon_swlocked_write(val, EP93XX_SYSCON_I2SCLKDIV); |
700 | |
701 | return 0; |
702 | } |
703 | EXPORT_SYMBOL(ep93xx_i2s_acquire); |
704 | |
705 | void ep93xx_i2s_release(void) |
706 | { |
707 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK); |
708 | } |
709 | EXPORT_SYMBOL(ep93xx_i2s_release); |
710 | |
711 | /************************************************************************* |
712 | * EP93xx AC97 audio peripheral handling |
713 | *************************************************************************/ |
714 | static struct resource ep93xx_ac97_resources[] = { |
715 | DEFINE_RES_MEM(EP93XX_AAC_PHYS_BASE, 0xac), |
716 | DEFINE_RES_IRQ(IRQ_EP93XX_AACINTR), |
717 | }; |
718 | |
719 | static struct platform_device ep93xx_ac97_device = { |
720 | .name = "ep93xx-ac97" , |
721 | .id = -1, |
722 | .num_resources = ARRAY_SIZE(ep93xx_ac97_resources), |
723 | .resource = ep93xx_ac97_resources, |
724 | }; |
725 | |
726 | void __init ep93xx_register_ac97(void) |
727 | { |
728 | /* |
729 | * Make sure that the AC97 pins are not used by I2S. |
730 | */ |
731 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2SONAC97); |
732 | |
733 | platform_device_register(&ep93xx_ac97_device); |
734 | platform_device_register(&ep93xx_pcm_device); |
735 | } |
736 | |
737 | /************************************************************************* |
738 | * EP93xx Watchdog |
739 | *************************************************************************/ |
740 | static struct resource ep93xx_wdt_resources[] = { |
741 | DEFINE_RES_MEM(EP93XX_WATCHDOG_PHYS_BASE, 0x08), |
742 | }; |
743 | |
744 | static struct platform_device ep93xx_wdt_device = { |
745 | .name = "ep93xx-wdt" , |
746 | .id = -1, |
747 | .num_resources = ARRAY_SIZE(ep93xx_wdt_resources), |
748 | .resource = ep93xx_wdt_resources, |
749 | }; |
750 | |
751 | /************************************************************************* |
752 | * EP93xx IDE |
753 | *************************************************************************/ |
754 | static struct resource ep93xx_ide_resources[] = { |
755 | DEFINE_RES_MEM(EP93XX_IDE_PHYS_BASE, 0x38), |
756 | DEFINE_RES_IRQ(IRQ_EP93XX_EXT3), |
757 | }; |
758 | |
759 | static struct platform_device ep93xx_ide_device = { |
760 | .name = "ep93xx-ide" , |
761 | .id = -1, |
762 | .dev = { |
763 | .dma_mask = &ep93xx_ide_device.dev.coherent_dma_mask, |
764 | .coherent_dma_mask = DMA_BIT_MASK(32), |
765 | }, |
766 | .num_resources = ARRAY_SIZE(ep93xx_ide_resources), |
767 | .resource = ep93xx_ide_resources, |
768 | }; |
769 | |
770 | void __init ep93xx_register_ide(void) |
771 | { |
772 | platform_device_register(&ep93xx_ide_device); |
773 | } |
774 | |
775 | int ep93xx_ide_acquire_gpio(struct platform_device *pdev) |
776 | { |
777 | int err; |
778 | int i; |
779 | |
780 | err = gpio_request(EP93XX_GPIO_LINE_EGPIO2, label: dev_name(dev: &pdev->dev)); |
781 | if (err) |
782 | return err; |
783 | err = gpio_request(EP93XX_GPIO_LINE_EGPIO15, label: dev_name(dev: &pdev->dev)); |
784 | if (err) |
785 | goto fail_egpio15; |
786 | for (i = 2; i < 8; i++) { |
787 | err = gpio_request(EP93XX_GPIO_LINE_E(i), label: dev_name(dev: &pdev->dev)); |
788 | if (err) |
789 | goto fail_gpio_e; |
790 | } |
791 | for (i = 4; i < 8; i++) { |
792 | err = gpio_request(EP93XX_GPIO_LINE_G(i), label: dev_name(dev: &pdev->dev)); |
793 | if (err) |
794 | goto fail_gpio_g; |
795 | } |
796 | for (i = 0; i < 8; i++) { |
797 | err = gpio_request(EP93XX_GPIO_LINE_H(i), label: dev_name(dev: &pdev->dev)); |
798 | if (err) |
799 | goto fail_gpio_h; |
800 | } |
801 | |
802 | /* GPIO ports E[7:2], G[7:4] and H used by IDE */ |
803 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_EONIDE | |
804 | EP93XX_SYSCON_DEVCFG_GONIDE | |
805 | EP93XX_SYSCON_DEVCFG_HONIDE); |
806 | return 0; |
807 | |
808 | fail_gpio_h: |
809 | for (--i; i >= 0; --i) |
810 | gpio_free(EP93XX_GPIO_LINE_H(i)); |
811 | i = 8; |
812 | fail_gpio_g: |
813 | for (--i; i >= 4; --i) |
814 | gpio_free(EP93XX_GPIO_LINE_G(i)); |
815 | i = 8; |
816 | fail_gpio_e: |
817 | for (--i; i >= 2; --i) |
818 | gpio_free(EP93XX_GPIO_LINE_E(i)); |
819 | gpio_free(EP93XX_GPIO_LINE_EGPIO15); |
820 | fail_egpio15: |
821 | gpio_free(EP93XX_GPIO_LINE_EGPIO2); |
822 | return err; |
823 | } |
824 | EXPORT_SYMBOL(ep93xx_ide_acquire_gpio); |
825 | |
826 | void ep93xx_ide_release_gpio(struct platform_device *pdev) |
827 | { |
828 | int i; |
829 | |
830 | for (i = 2; i < 8; i++) |
831 | gpio_free(EP93XX_GPIO_LINE_E(i)); |
832 | for (i = 4; i < 8; i++) |
833 | gpio_free(EP93XX_GPIO_LINE_G(i)); |
834 | for (i = 0; i < 8; i++) |
835 | gpio_free(EP93XX_GPIO_LINE_H(i)); |
836 | gpio_free(EP93XX_GPIO_LINE_EGPIO15); |
837 | gpio_free(EP93XX_GPIO_LINE_EGPIO2); |
838 | |
839 | |
840 | /* GPIO ports E[7:2], G[7:4] and H used by GPIO */ |
841 | ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_EONIDE | |
842 | EP93XX_SYSCON_DEVCFG_GONIDE | |
843 | EP93XX_SYSCON_DEVCFG_HONIDE); |
844 | } |
845 | EXPORT_SYMBOL(ep93xx_ide_release_gpio); |
846 | |
847 | /************************************************************************* |
848 | * EP93xx ADC |
849 | *************************************************************************/ |
850 | static struct resource ep93xx_adc_resources[] = { |
851 | DEFINE_RES_MEM(EP93XX_ADC_PHYS_BASE, 0x28), |
852 | DEFINE_RES_IRQ(IRQ_EP93XX_TOUCH), |
853 | }; |
854 | |
855 | static struct platform_device ep93xx_adc_device = { |
856 | .name = "ep93xx-adc" , |
857 | .id = -1, |
858 | .num_resources = ARRAY_SIZE(ep93xx_adc_resources), |
859 | .resource = ep93xx_adc_resources, |
860 | }; |
861 | |
862 | void __init ep93xx_register_adc(void) |
863 | { |
864 | /* Power up ADC, deactivate Touch Screen Controller */ |
865 | ep93xx_devcfg_set_clear(EP93XX_SYSCON_DEVCFG_TIN, |
866 | EP93XX_SYSCON_DEVCFG_ADCPD); |
867 | |
868 | platform_device_register(&ep93xx_adc_device); |
869 | } |
870 | |
871 | /************************************************************************* |
872 | * EP93xx Security peripheral |
873 | *************************************************************************/ |
874 | |
875 | /* |
876 | * The Maverick Key is 256 bits of micro fuses blown at the factory during |
877 | * manufacturing to uniquely identify a part. |
878 | * |
879 | * See: http://arm.cirrus.com/forum/viewtopic.php?t=486&highlight=maverick+key |
880 | */ |
881 | #define EP93XX_SECURITY_REG(x) (EP93XX_SECURITY_BASE + (x)) |
882 | #define EP93XX_SECURITY_SECFLG EP93XX_SECURITY_REG(0x2400) |
883 | #define EP93XX_SECURITY_FUSEFLG EP93XX_SECURITY_REG(0x2410) |
884 | #define EP93XX_SECURITY_UNIQID EP93XX_SECURITY_REG(0x2440) |
885 | #define EP93XX_SECURITY_UNIQCHK EP93XX_SECURITY_REG(0x2450) |
886 | #define EP93XX_SECURITY_UNIQVAL EP93XX_SECURITY_REG(0x2460) |
887 | #define EP93XX_SECURITY_SECID1 EP93XX_SECURITY_REG(0x2500) |
888 | #define EP93XX_SECURITY_SECID2 EP93XX_SECURITY_REG(0x2504) |
889 | #define EP93XX_SECURITY_SECCHK1 EP93XX_SECURITY_REG(0x2520) |
890 | #define EP93XX_SECURITY_SECCHK2 EP93XX_SECURITY_REG(0x2524) |
891 | #define EP93XX_SECURITY_UNIQID2 EP93XX_SECURITY_REG(0x2700) |
892 | #define EP93XX_SECURITY_UNIQID3 EP93XX_SECURITY_REG(0x2704) |
893 | #define EP93XX_SECURITY_UNIQID4 EP93XX_SECURITY_REG(0x2708) |
894 | #define EP93XX_SECURITY_UNIQID5 EP93XX_SECURITY_REG(0x270c) |
895 | |
896 | static char ep93xx_soc_id[33]; |
897 | |
898 | static const char __init *ep93xx_get_soc_id(void) |
899 | { |
900 | unsigned int id, id2, id3, id4, id5; |
901 | |
902 | if (__raw_readl(EP93XX_SECURITY_UNIQVAL) != 1) |
903 | return "bad Hamming code" ; |
904 | |
905 | id = __raw_readl(EP93XX_SECURITY_UNIQID); |
906 | id2 = __raw_readl(EP93XX_SECURITY_UNIQID2); |
907 | id3 = __raw_readl(EP93XX_SECURITY_UNIQID3); |
908 | id4 = __raw_readl(EP93XX_SECURITY_UNIQID4); |
909 | id5 = __raw_readl(EP93XX_SECURITY_UNIQID5); |
910 | |
911 | if (id != id2) |
912 | return "invalid" ; |
913 | |
914 | /* Toss the unique ID into the entropy pool */ |
915 | add_device_randomness(buf: &id2, len: 4); |
916 | add_device_randomness(buf: &id3, len: 4); |
917 | add_device_randomness(buf: &id4, len: 4); |
918 | add_device_randomness(buf: &id5, len: 4); |
919 | |
920 | snprintf(buf: ep93xx_soc_id, size: sizeof(ep93xx_soc_id), |
921 | fmt: "%08x%08x%08x%08x" , id2, id3, id4, id5); |
922 | |
923 | return ep93xx_soc_id; |
924 | } |
925 | |
926 | static const char __init *ep93xx_get_soc_rev(void) |
927 | { |
928 | int rev = ep93xx_chip_revision(); |
929 | |
930 | switch (rev) { |
931 | case EP93XX_CHIP_REV_D0: |
932 | return "D0" ; |
933 | case EP93XX_CHIP_REV_D1: |
934 | return "D1" ; |
935 | case EP93XX_CHIP_REV_E0: |
936 | return "E0" ; |
937 | case EP93XX_CHIP_REV_E1: |
938 | return "E1" ; |
939 | case EP93XX_CHIP_REV_E2: |
940 | return "E2" ; |
941 | default: |
942 | return "unknown" ; |
943 | } |
944 | } |
945 | |
946 | static const char __init *ep93xx_get_machine_name(void) |
947 | { |
948 | return kasprintf(GFP_KERNEL,fmt: "%s" , machine_desc->name); |
949 | } |
950 | |
951 | static struct device __init *ep93xx_init_soc(void) |
952 | { |
953 | struct soc_device_attribute *soc_dev_attr; |
954 | struct soc_device *soc_dev; |
955 | |
956 | soc_dev_attr = kzalloc(size: sizeof(*soc_dev_attr), GFP_KERNEL); |
957 | if (!soc_dev_attr) |
958 | return NULL; |
959 | |
960 | soc_dev_attr->machine = ep93xx_get_machine_name(); |
961 | soc_dev_attr->family = "Cirrus Logic EP93xx" ; |
962 | soc_dev_attr->revision = ep93xx_get_soc_rev(); |
963 | soc_dev_attr->soc_id = ep93xx_get_soc_id(); |
964 | |
965 | soc_dev = soc_device_register(soc_plat_dev_attr: soc_dev_attr); |
966 | if (IS_ERR(ptr: soc_dev)) { |
967 | kfree(objp: soc_dev_attr->machine); |
968 | kfree(objp: soc_dev_attr); |
969 | return NULL; |
970 | } |
971 | |
972 | return soc_device_to_device(soc: soc_dev); |
973 | } |
974 | |
975 | struct device __init *ep93xx_init_devices(void) |
976 | { |
977 | struct device *parent; |
978 | |
979 | /* Disallow access to MaverickCrunch initially */ |
980 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA); |
981 | |
982 | /* Default all ports to GPIO */ |
983 | ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS | |
984 | EP93XX_SYSCON_DEVCFG_GONK | |
985 | EP93XX_SYSCON_DEVCFG_EONIDE | |
986 | EP93XX_SYSCON_DEVCFG_GONIDE | |
987 | EP93XX_SYSCON_DEVCFG_HONIDE); |
988 | |
989 | parent = ep93xx_init_soc(); |
990 | |
991 | /* Get the GPIO working early, other devices need it */ |
992 | platform_device_register(&ep93xx_gpio_device); |
993 | |
994 | amba_device_register(&uart1_device, &iomem_resource); |
995 | amba_device_register(&uart2_device, &iomem_resource); |
996 | amba_device_register(&uart3_device, &iomem_resource); |
997 | |
998 | platform_device_register(&ep93xx_rtc_device); |
999 | platform_device_register(&ep93xx_ohci_device); |
1000 | platform_device_register(&ep93xx_wdt_device); |
1001 | |
1002 | gpiod_add_lookup_table(table: &ep93xx_leds_gpio_table); |
1003 | gpio_led_register_device(id: -1, pdata: &ep93xx_led_data); |
1004 | |
1005 | return parent; |
1006 | } |
1007 | |
1008 | void ep93xx_restart(enum reboot_mode mode, const char *cmd) |
1009 | { |
1010 | /* |
1011 | * Set then clear the SWRST bit to initiate a software reset |
1012 | */ |
1013 | ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_SWRST); |
1014 | ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_SWRST); |
1015 | |
1016 | while (1) |
1017 | ; |
1018 | } |
1019 | |