1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * arch/arm/mach-ep93xx/vision_ep9307.c
4*4882a593Smuzhiyun * Vision Engraving Systems EP9307 SoM support.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright (C) 2008-2011 Vision Engraving Systems
7*4882a593Smuzhiyun * H Hartley Sweeten <hsweeten@visionengravers.com>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/kernel.h>
13*4882a593Smuzhiyun #include <linux/init.h>
14*4882a593Smuzhiyun #include <linux/platform_device.h>
15*4882a593Smuzhiyun #include <linux/irq.h>
16*4882a593Smuzhiyun #include <linux/gpio.h>
17*4882a593Smuzhiyun #include <linux/gpio/machine.h>
18*4882a593Smuzhiyun #include <linux/fb.h>
19*4882a593Smuzhiyun #include <linux/io.h>
20*4882a593Smuzhiyun #include <linux/mtd/partitions.h>
21*4882a593Smuzhiyun #include <linux/i2c.h>
22*4882a593Smuzhiyun #include <linux/platform_data/pca953x.h>
23*4882a593Smuzhiyun #include <linux/spi/spi.h>
24*4882a593Smuzhiyun #include <linux/spi/flash.h>
25*4882a593Smuzhiyun #include <linux/spi/mmc_spi.h>
26*4882a593Smuzhiyun #include <linux/mmc/host.h>
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #include <sound/cs4271.h>
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #include "hardware.h"
31*4882a593Smuzhiyun #include <linux/platform_data/video-ep93xx.h>
32*4882a593Smuzhiyun #include <linux/platform_data/spi-ep93xx.h>
33*4882a593Smuzhiyun #include "gpio-ep93xx.h"
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #include <asm/mach-types.h>
36*4882a593Smuzhiyun #include <asm/mach/map.h>
37*4882a593Smuzhiyun #include <asm/mach/arch.h>
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #include "soc.h"
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun /*************************************************************************
42*4882a593Smuzhiyun * Static I/O mappings for the FPGA
43*4882a593Smuzhiyun *************************************************************************/
44*4882a593Smuzhiyun #define VISION_PHYS_BASE EP93XX_CS7_PHYS_BASE
45*4882a593Smuzhiyun #define VISION_VIRT_BASE 0xfebff000
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun static struct map_desc vision_io_desc[] __initdata = {
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun .virtual = VISION_VIRT_BASE,
50*4882a593Smuzhiyun .pfn = __phys_to_pfn(VISION_PHYS_BASE),
51*4882a593Smuzhiyun .length = SZ_4K,
52*4882a593Smuzhiyun .type = MT_DEVICE,
53*4882a593Smuzhiyun },
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun
vision_map_io(void)56*4882a593Smuzhiyun static void __init vision_map_io(void)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun ep93xx_map_io();
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun iotable_init(vision_io_desc, ARRAY_SIZE(vision_io_desc));
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun /*************************************************************************
64*4882a593Smuzhiyun * Ethernet
65*4882a593Smuzhiyun *************************************************************************/
66*4882a593Smuzhiyun static struct ep93xx_eth_data vision_eth_data __initdata = {
67*4882a593Smuzhiyun .phy_id = 1,
68*4882a593Smuzhiyun };
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /*************************************************************************
71*4882a593Smuzhiyun * Framebuffer
72*4882a593Smuzhiyun *************************************************************************/
73*4882a593Smuzhiyun #define VISION_LCD_ENABLE EP93XX_GPIO_LINE_EGPIO1
74*4882a593Smuzhiyun
vision_lcd_setup(struct platform_device * pdev)75*4882a593Smuzhiyun static int vision_lcd_setup(struct platform_device *pdev)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun int err;
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun err = gpio_request_one(VISION_LCD_ENABLE, GPIOF_INIT_HIGH,
80*4882a593Smuzhiyun dev_name(&pdev->dev));
81*4882a593Smuzhiyun if (err)
82*4882a593Smuzhiyun return err;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_RAS |
85*4882a593Smuzhiyun EP93XX_SYSCON_DEVCFG_RASONP3 |
86*4882a593Smuzhiyun EP93XX_SYSCON_DEVCFG_EXVC);
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun return 0;
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun
vision_lcd_teardown(struct platform_device * pdev)91*4882a593Smuzhiyun static void vision_lcd_teardown(struct platform_device *pdev)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun gpio_free(VISION_LCD_ENABLE);
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun
vision_lcd_blank(int blank_mode,struct fb_info * info)96*4882a593Smuzhiyun static void vision_lcd_blank(int blank_mode, struct fb_info *info)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun if (blank_mode)
99*4882a593Smuzhiyun gpio_set_value(VISION_LCD_ENABLE, 0);
100*4882a593Smuzhiyun else
101*4882a593Smuzhiyun gpio_set_value(VISION_LCD_ENABLE, 1);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun static struct ep93xxfb_mach_info ep93xxfb_info __initdata = {
105*4882a593Smuzhiyun .flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING,
106*4882a593Smuzhiyun .setup = vision_lcd_setup,
107*4882a593Smuzhiyun .teardown = vision_lcd_teardown,
108*4882a593Smuzhiyun .blank = vision_lcd_blank,
109*4882a593Smuzhiyun };
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun /*************************************************************************
113*4882a593Smuzhiyun * GPIO Expanders
114*4882a593Smuzhiyun *************************************************************************/
115*4882a593Smuzhiyun #define PCA9539_74_GPIO_BASE (EP93XX_GPIO_LINE_MAX + 1)
116*4882a593Smuzhiyun #define PCA9539_75_GPIO_BASE (PCA9539_74_GPIO_BASE + 16)
117*4882a593Smuzhiyun #define PCA9539_76_GPIO_BASE (PCA9539_75_GPIO_BASE + 16)
118*4882a593Smuzhiyun #define PCA9539_77_GPIO_BASE (PCA9539_76_GPIO_BASE + 16)
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun static struct pca953x_platform_data pca953x_74_gpio_data = {
121*4882a593Smuzhiyun .gpio_base = PCA9539_74_GPIO_BASE,
122*4882a593Smuzhiyun .irq_base = EP93XX_BOARD_IRQ(0),
123*4882a593Smuzhiyun };
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun static struct pca953x_platform_data pca953x_75_gpio_data = {
126*4882a593Smuzhiyun .gpio_base = PCA9539_75_GPIO_BASE,
127*4882a593Smuzhiyun .irq_base = -1,
128*4882a593Smuzhiyun };
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun static struct pca953x_platform_data pca953x_76_gpio_data = {
131*4882a593Smuzhiyun .gpio_base = PCA9539_76_GPIO_BASE,
132*4882a593Smuzhiyun .irq_base = -1,
133*4882a593Smuzhiyun };
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun static struct pca953x_platform_data pca953x_77_gpio_data = {
136*4882a593Smuzhiyun .gpio_base = PCA9539_77_GPIO_BASE,
137*4882a593Smuzhiyun .irq_base = -1,
138*4882a593Smuzhiyun };
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun /*************************************************************************
141*4882a593Smuzhiyun * I2C Bus
142*4882a593Smuzhiyun *************************************************************************/
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun static struct i2c_board_info vision_i2c_info[] __initdata = {
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun I2C_BOARD_INFO("isl1208", 0x6f),
147*4882a593Smuzhiyun .irq = IRQ_EP93XX_EXT1,
148*4882a593Smuzhiyun }, {
149*4882a593Smuzhiyun I2C_BOARD_INFO("pca9539", 0x74),
150*4882a593Smuzhiyun .platform_data = &pca953x_74_gpio_data,
151*4882a593Smuzhiyun }, {
152*4882a593Smuzhiyun I2C_BOARD_INFO("pca9539", 0x75),
153*4882a593Smuzhiyun .platform_data = &pca953x_75_gpio_data,
154*4882a593Smuzhiyun }, {
155*4882a593Smuzhiyun I2C_BOARD_INFO("pca9539", 0x76),
156*4882a593Smuzhiyun .platform_data = &pca953x_76_gpio_data,
157*4882a593Smuzhiyun }, {
158*4882a593Smuzhiyun I2C_BOARD_INFO("pca9539", 0x77),
159*4882a593Smuzhiyun .platform_data = &pca953x_77_gpio_data,
160*4882a593Smuzhiyun },
161*4882a593Smuzhiyun };
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun /*************************************************************************
164*4882a593Smuzhiyun * SPI CS4271 Audio Codec
165*4882a593Smuzhiyun *************************************************************************/
166*4882a593Smuzhiyun static struct cs4271_platform_data vision_cs4271_data = {
167*4882a593Smuzhiyun .gpio_nreset = EP93XX_GPIO_LINE_H(2),
168*4882a593Smuzhiyun };
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun /*************************************************************************
171*4882a593Smuzhiyun * SPI Flash
172*4882a593Smuzhiyun *************************************************************************/
173*4882a593Smuzhiyun static struct mtd_partition vision_spi_flash_partitions[] = {
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun .name = "SPI bootstrap",
176*4882a593Smuzhiyun .offset = 0,
177*4882a593Smuzhiyun .size = SZ_4K,
178*4882a593Smuzhiyun }, {
179*4882a593Smuzhiyun .name = "Bootstrap config",
180*4882a593Smuzhiyun .offset = MTDPART_OFS_APPEND,
181*4882a593Smuzhiyun .size = SZ_4K,
182*4882a593Smuzhiyun }, {
183*4882a593Smuzhiyun .name = "System config",
184*4882a593Smuzhiyun .offset = MTDPART_OFS_APPEND,
185*4882a593Smuzhiyun .size = MTDPART_SIZ_FULL,
186*4882a593Smuzhiyun },
187*4882a593Smuzhiyun };
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun static struct flash_platform_data vision_spi_flash_data = {
190*4882a593Smuzhiyun .name = "SPI Flash",
191*4882a593Smuzhiyun .parts = vision_spi_flash_partitions,
192*4882a593Smuzhiyun .nr_parts = ARRAY_SIZE(vision_spi_flash_partitions),
193*4882a593Smuzhiyun };
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun /*************************************************************************
196*4882a593Smuzhiyun * SPI SD/MMC host
197*4882a593Smuzhiyun *************************************************************************/
198*4882a593Smuzhiyun static struct mmc_spi_platform_data vision_spi_mmc_data = {
199*4882a593Smuzhiyun .detect_delay = 100,
200*4882a593Smuzhiyun .powerup_msecs = 100,
201*4882a593Smuzhiyun .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
202*4882a593Smuzhiyun .caps2 = MMC_CAP2_RO_ACTIVE_HIGH,
203*4882a593Smuzhiyun };
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun static struct gpiod_lookup_table vision_spi_mmc_gpio_table = {
206*4882a593Smuzhiyun .dev_id = "mmc_spi.2", /* "mmc_spi @ CS2 */
207*4882a593Smuzhiyun .table = {
208*4882a593Smuzhiyun /* Card detect */
209*4882a593Smuzhiyun GPIO_LOOKUP_IDX("B", 7, NULL, 0, GPIO_ACTIVE_LOW),
210*4882a593Smuzhiyun /* Write protect */
211*4882a593Smuzhiyun GPIO_LOOKUP_IDX("F", 0, NULL, 1, GPIO_ACTIVE_HIGH),
212*4882a593Smuzhiyun { },
213*4882a593Smuzhiyun },
214*4882a593Smuzhiyun };
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun /*************************************************************************
217*4882a593Smuzhiyun * SPI Bus
218*4882a593Smuzhiyun *************************************************************************/
219*4882a593Smuzhiyun static struct spi_board_info vision_spi_board_info[] __initdata = {
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun .modalias = "cs4271",
222*4882a593Smuzhiyun .platform_data = &vision_cs4271_data,
223*4882a593Smuzhiyun .max_speed_hz = 6000000,
224*4882a593Smuzhiyun .bus_num = 0,
225*4882a593Smuzhiyun .chip_select = 0,
226*4882a593Smuzhiyun .mode = SPI_MODE_3,
227*4882a593Smuzhiyun }, {
228*4882a593Smuzhiyun .modalias = "sst25l",
229*4882a593Smuzhiyun .platform_data = &vision_spi_flash_data,
230*4882a593Smuzhiyun .max_speed_hz = 20000000,
231*4882a593Smuzhiyun .bus_num = 0,
232*4882a593Smuzhiyun .chip_select = 1,
233*4882a593Smuzhiyun .mode = SPI_MODE_3,
234*4882a593Smuzhiyun }, {
235*4882a593Smuzhiyun .modalias = "mmc_spi",
236*4882a593Smuzhiyun .platform_data = &vision_spi_mmc_data,
237*4882a593Smuzhiyun .max_speed_hz = 20000000,
238*4882a593Smuzhiyun .bus_num = 0,
239*4882a593Smuzhiyun .chip_select = 2,
240*4882a593Smuzhiyun .mode = SPI_MODE_3,
241*4882a593Smuzhiyun },
242*4882a593Smuzhiyun };
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun static struct gpiod_lookup_table vision_spi_cs_gpio_table = {
245*4882a593Smuzhiyun .dev_id = "spi0",
246*4882a593Smuzhiyun .table = {
247*4882a593Smuzhiyun GPIO_LOOKUP_IDX("A", 6, "cs", 0, GPIO_ACTIVE_LOW),
248*4882a593Smuzhiyun GPIO_LOOKUP_IDX("A", 7, "cs", 1, GPIO_ACTIVE_LOW),
249*4882a593Smuzhiyun GPIO_LOOKUP_IDX("G", 2, "cs", 2, GPIO_ACTIVE_LOW),
250*4882a593Smuzhiyun { },
251*4882a593Smuzhiyun },
252*4882a593Smuzhiyun };
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun static struct ep93xx_spi_info vision_spi_master __initdata = {
255*4882a593Smuzhiyun .use_dma = 1,
256*4882a593Smuzhiyun };
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun /*************************************************************************
259*4882a593Smuzhiyun * I2S Audio
260*4882a593Smuzhiyun *************************************************************************/
261*4882a593Smuzhiyun static struct platform_device vision_audio_device = {
262*4882a593Smuzhiyun .name = "edb93xx-audio",
263*4882a593Smuzhiyun .id = -1,
264*4882a593Smuzhiyun };
265*4882a593Smuzhiyun
vision_register_i2s(void)266*4882a593Smuzhiyun static void __init vision_register_i2s(void)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun ep93xx_register_i2s();
269*4882a593Smuzhiyun platform_device_register(&vision_audio_device);
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun /*************************************************************************
273*4882a593Smuzhiyun * Machine Initialization
274*4882a593Smuzhiyun *************************************************************************/
vision_init_machine(void)275*4882a593Smuzhiyun static void __init vision_init_machine(void)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun ep93xx_init_devices();
278*4882a593Smuzhiyun ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_64M);
279*4882a593Smuzhiyun ep93xx_register_eth(&vision_eth_data, 1);
280*4882a593Smuzhiyun ep93xx_register_fb(&ep93xxfb_info);
281*4882a593Smuzhiyun ep93xx_register_pwm(1, 0);
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun /*
284*4882a593Smuzhiyun * Request the gpio expander's interrupt gpio line now to prevent
285*4882a593Smuzhiyun * the kernel from doing a WARN in gpiolib:gpio_ensure_requested().
286*4882a593Smuzhiyun */
287*4882a593Smuzhiyun if (gpio_request_one(EP93XX_GPIO_LINE_F(7), GPIOF_DIR_IN,
288*4882a593Smuzhiyun "pca9539:74"))
289*4882a593Smuzhiyun pr_warn("cannot request interrupt gpio for pca9539:74\n");
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun vision_i2c_info[1].irq = gpio_to_irq(EP93XX_GPIO_LINE_F(7));
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun ep93xx_register_i2c(vision_i2c_info,
294*4882a593Smuzhiyun ARRAY_SIZE(vision_i2c_info));
295*4882a593Smuzhiyun gpiod_add_lookup_table(&vision_spi_mmc_gpio_table);
296*4882a593Smuzhiyun gpiod_add_lookup_table(&vision_spi_cs_gpio_table);
297*4882a593Smuzhiyun ep93xx_register_spi(&vision_spi_master, vision_spi_board_info,
298*4882a593Smuzhiyun ARRAY_SIZE(vision_spi_board_info));
299*4882a593Smuzhiyun vision_register_i2s();
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun MACHINE_START(VISION_EP9307, "Vision Engraving Systems EP9307")
303*4882a593Smuzhiyun /* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
304*4882a593Smuzhiyun .atag_offset = 0x100,
305*4882a593Smuzhiyun .map_io = vision_map_io,
306*4882a593Smuzhiyun .init_irq = ep93xx_init_irq,
307*4882a593Smuzhiyun .init_time = ep93xx_timer_init,
308*4882a593Smuzhiyun .init_machine = vision_init_machine,
309*4882a593Smuzhiyun .init_late = ep93xx_init_late,
310*4882a593Smuzhiyun .restart = ep93xx_restart,
311*4882a593Smuzhiyun MACHINE_END
312