Icarus Chau | 9855895 | 2015-03-03 19:36:03 -0800 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright (C) 2015 Broadcom Corporation |
| 3 | * |
| 4 | * This program is free software; you can redistribute it and/or |
| 5 | * modify it under the terms of the GNU General Public License as |
| 6 | * published by the Free Software Foundation version 2. |
| 7 | * |
| 8 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any |
| 9 | * kind, whether express or implied; without even the implied warranty |
| 10 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 11 | * GNU General Public License for more details. |
| 12 | */ |
| 13 | |
| 14 | #include <arch/io.h> |
| 15 | #include <console/console.h> |
| 16 | #include <gpio.h> |
| 17 | #include <stdlib.h> |
| 18 | #include <string.h> |
| 19 | #include <soc/addressmap.h> |
| 20 | |
| 21 | #define CYGNUS_NUM_IOMUX_REGS 8 |
| 22 | #define CYGNUS_NUM_MUX_PER_REG 8 |
| 23 | #define CYGNUS_NUM_IOMUX (CYGNUS_NUM_IOMUX_REGS * \ |
| 24 | CYGNUS_NUM_MUX_PER_REG) |
| 25 | |
| 26 | /* |
| 27 | * Cygnus IOMUX pinctrl core |
| 28 | * |
| 29 | * @base1: second I/O register base |
| 30 | */ |
| 31 | struct cygnus_pinctrl { |
| 32 | void *base1; |
| 33 | }; |
| 34 | |
| 35 | static struct cygnus_pinctrl pinctrl_data = { |
| 36 | .base1 = (void *)IPROC_IOMUX_OVERRIDE_BASE |
| 37 | }; |
| 38 | |
| 39 | /* |
| 40 | * Certain pins can be individually muxed to GPIO function |
| 41 | * |
| 42 | * @is_supported: flag to indicate GPIO mux is supported for this pin |
| 43 | * @offset: register offset for GPIO mux override of a pin |
| 44 | * @shift: bit shift for GPIO mux override of a pin |
| 45 | */ |
| 46 | struct cygnus_gpio_mux { |
| 47 | int is_supported; |
| 48 | unsigned int offset; |
| 49 | unsigned int shift; |
| 50 | }; |
| 51 | |
| 52 | /* |
| 53 | * Description of a pin in Cygnus |
| 54 | * |
| 55 | * @pin: pin number |
| 56 | * @name: pin name |
| 57 | * @gpio_mux: GPIO override related information |
| 58 | */ |
| 59 | struct cygnus_pin { |
| 60 | unsigned pin; |
| 61 | const char *name; |
| 62 | struct cygnus_gpio_mux gpio_mux; |
| 63 | }; |
| 64 | |
| 65 | #define CYGNUS_PIN_DESC(p, n, i, o, s) \ |
| 66 | { \ |
| 67 | .pin = p, \ |
| 68 | .name = n, \ |
| 69 | .gpio_mux = { \ |
| 70 | .is_supported = i, \ |
| 71 | .offset = o, \ |
| 72 | .shift = s, \ |
| 73 | }, \ |
| 74 | } |
| 75 | |
| 76 | /* |
| 77 | * List of pins in Cygnus |
| 78 | */ |
| 79 | static struct cygnus_pin cygnus_pins[] = { |
| 80 | CYGNUS_PIN_DESC(0, "ext_device_reset_n", 0, 0, 0), |
| 81 | CYGNUS_PIN_DESC(1, "chip_mode0", 0, 0, 0), |
| 82 | CYGNUS_PIN_DESC(2, "chip_mode1", 0, 0, 0), |
| 83 | CYGNUS_PIN_DESC(3, "chip_mode2", 0, 0, 0), |
| 84 | CYGNUS_PIN_DESC(4, "chip_mode3", 0, 0, 0), |
| 85 | CYGNUS_PIN_DESC(5, "chip_mode4", 0, 0, 0), |
| 86 | CYGNUS_PIN_DESC(6, "bsc0_scl", 0, 0, 0), |
| 87 | CYGNUS_PIN_DESC(7, "bsc0_sda", 0, 0, 0), |
| 88 | CYGNUS_PIN_DESC(8, "bsc1_scl", 0, 0, 0), |
| 89 | CYGNUS_PIN_DESC(9, "bsc1_sda", 0, 0, 0), |
| 90 | CYGNUS_PIN_DESC(10, "d1w_dq", 1, 0x28, 0), |
| 91 | CYGNUS_PIN_DESC(11, "d1wowstz_l", 1, 0x4, 28), |
| 92 | CYGNUS_PIN_DESC(12, "gpio0", 0, 0, 0), |
| 93 | CYGNUS_PIN_DESC(13, "gpio1", 0, 0, 0), |
| 94 | CYGNUS_PIN_DESC(14, "gpio2", 0, 0, 0), |
| 95 | CYGNUS_PIN_DESC(15, "gpio3", 0, 0, 0), |
| 96 | CYGNUS_PIN_DESC(16, "gpio4", 0, 0, 0), |
| 97 | CYGNUS_PIN_DESC(17, "gpio5", 0, 0, 0), |
| 98 | CYGNUS_PIN_DESC(18, "gpio6", 0, 0, 0), |
| 99 | CYGNUS_PIN_DESC(19, "gpio7", 0, 0, 0), |
| 100 | CYGNUS_PIN_DESC(20, "gpio8", 0, 0, 0), |
| 101 | CYGNUS_PIN_DESC(21, "gpio9", 0, 0, 0), |
| 102 | CYGNUS_PIN_DESC(22, "gpio10", 0, 0, 0), |
| 103 | CYGNUS_PIN_DESC(23, "gpio11", 0, 0, 0), |
| 104 | CYGNUS_PIN_DESC(24, "gpio12", 0, 0, 0), |
| 105 | CYGNUS_PIN_DESC(25, "gpio13", 0, 0, 0), |
| 106 | CYGNUS_PIN_DESC(26, "gpio14", 0, 0, 0), |
| 107 | CYGNUS_PIN_DESC(27, "gpio15", 0, 0, 0), |
| 108 | CYGNUS_PIN_DESC(28, "gpio16", 0, 0, 0), |
| 109 | CYGNUS_PIN_DESC(29, "gpio17", 0, 0, 0), |
| 110 | CYGNUS_PIN_DESC(30, "gpio18", 0, 0, 0), |
| 111 | CYGNUS_PIN_DESC(31, "gpio19", 0, 0, 0), |
| 112 | CYGNUS_PIN_DESC(32, "gpio20", 0, 0, 0), |
| 113 | CYGNUS_PIN_DESC(33, "gpio21", 0, 0, 0), |
| 114 | CYGNUS_PIN_DESC(34, "gpio22", 0, 0, 0), |
| 115 | CYGNUS_PIN_DESC(35, "gpio23", 0, 0, 0), |
| 116 | CYGNUS_PIN_DESC(36, "mdc", 0, 0, 0), |
| 117 | CYGNUS_PIN_DESC(37, "mdio", 0, 0, 0), |
| 118 | CYGNUS_PIN_DESC(38, "pwm0", 1, 0x10, 30), |
| 119 | CYGNUS_PIN_DESC(39, "pwm1", 1, 0x10, 28), |
| 120 | CYGNUS_PIN_DESC(40, "pwm2", 1, 0x10, 26), |
| 121 | CYGNUS_PIN_DESC(41, "pwm3", 1, 0x10, 24), |
| 122 | CYGNUS_PIN_DESC(42, "sc0_clk", 1, 0x10, 22), |
| 123 | CYGNUS_PIN_DESC(43, "sc0_cmdvcc_l", 1, 0x10, 20), |
| 124 | CYGNUS_PIN_DESC(44, "sc0_detect", 1, 0x10, 18), |
| 125 | CYGNUS_PIN_DESC(45, "sc0_fcb", 1, 0x10, 16), |
| 126 | CYGNUS_PIN_DESC(46, "sc0_io", 1, 0x10, 14), |
| 127 | CYGNUS_PIN_DESC(47, "sc0_rst_l", 1, 0x10, 12), |
| 128 | CYGNUS_PIN_DESC(48, "sc1_clk", 1, 0x10, 10), |
| 129 | CYGNUS_PIN_DESC(49, "sc1_cmdvcc_l", 1, 0x10, 8), |
| 130 | CYGNUS_PIN_DESC(50, "sc1_detect", 1, 0x10, 6), |
| 131 | CYGNUS_PIN_DESC(51, "sc1_fcb", 1, 0x10, 4), |
| 132 | CYGNUS_PIN_DESC(52, "sc1_io", 1, 0x10, 2), |
| 133 | CYGNUS_PIN_DESC(53, "sc1_rst_l", 1, 0x10, 0), |
| 134 | CYGNUS_PIN_DESC(54, "spi0_clk", 1, 0x18, 10), |
| 135 | CYGNUS_PIN_DESC(55, "spi0_mosi", 1, 0x18, 6), |
| 136 | CYGNUS_PIN_DESC(56, "spi0_miso", 1, 0x18, 8), |
| 137 | CYGNUS_PIN_DESC(57, "spi0_ss", 1, 0x18, 4), |
| 138 | CYGNUS_PIN_DESC(58, "spi1_clk", 1, 0x18, 2), |
| 139 | CYGNUS_PIN_DESC(59, "spi1_mosi", 1, 0x1c, 30), |
| 140 | CYGNUS_PIN_DESC(60, "spi1_miso", 1, 0x18, 0), |
| 141 | CYGNUS_PIN_DESC(61, "spi1_ss", 1, 0x1c, 28), |
| 142 | CYGNUS_PIN_DESC(62, "spi2_clk", 1, 0x1c, 26), |
| 143 | CYGNUS_PIN_DESC(63, "spi2_mosi", 1, 0x1c, 22), |
| 144 | CYGNUS_PIN_DESC(64, "spi2_miso", 1, 0x1c, 24), |
| 145 | CYGNUS_PIN_DESC(65, "spi2_ss", 1, 0x1c, 20), |
| 146 | CYGNUS_PIN_DESC(66, "spi3_clk", 1, 0x1c, 18), |
| 147 | CYGNUS_PIN_DESC(67, "spi3_mosi", 1, 0x1c, 14), |
| 148 | CYGNUS_PIN_DESC(68, "spi3_miso", 1, 0x1c, 16), |
| 149 | CYGNUS_PIN_DESC(69, "spi3_ss", 1, 0x1c, 12), |
| 150 | CYGNUS_PIN_DESC(70, "uart0_cts", 1, 0x1c, 10), |
| 151 | CYGNUS_PIN_DESC(71, "uart0_rts", 1, 0x1c, 8), |
| 152 | CYGNUS_PIN_DESC(72, "uart0_rx", 1, 0x1c, 6), |
| 153 | CYGNUS_PIN_DESC(73, "uart0_tx", 1, 0x1c, 4), |
| 154 | CYGNUS_PIN_DESC(74, "uart1_cts", 1, 0x1c, 2), |
| 155 | CYGNUS_PIN_DESC(75, "uart1_dcd", 1, 0x1c, 0), |
| 156 | CYGNUS_PIN_DESC(76, "uart1_dsr", 1, 0x20, 14), |
| 157 | CYGNUS_PIN_DESC(77, "uart1_dtr", 1, 0x20, 12), |
| 158 | CYGNUS_PIN_DESC(78, "uart1_ri", 1, 0x20, 10), |
| 159 | CYGNUS_PIN_DESC(79, "uart1_rts", 1, 0x20, 8), |
| 160 | CYGNUS_PIN_DESC(80, "uart1_rx", 1, 0x20, 6), |
| 161 | CYGNUS_PIN_DESC(81, "uart1_tx", 1, 0x20, 4), |
| 162 | CYGNUS_PIN_DESC(82, "uart3_rx", 1, 0x20, 2), |
| 163 | CYGNUS_PIN_DESC(83, "uart3_tx", 1, 0x20, 0), |
| 164 | CYGNUS_PIN_DESC(84, "sdio1_clk_sdcard", 1, 0x14, 6), |
| 165 | CYGNUS_PIN_DESC(85, "sdio1_cmd", 1, 0x14, 4), |
| 166 | CYGNUS_PIN_DESC(86, "sdio1_data0", 1, 0x14, 2), |
| 167 | CYGNUS_PIN_DESC(87, "sdio1_data1", 1, 0x14, 0), |
| 168 | CYGNUS_PIN_DESC(88, "sdio1_data2", 1, 0x18, 30), |
| 169 | CYGNUS_PIN_DESC(89, "sdio1_data3", 1, 0x18, 28), |
| 170 | CYGNUS_PIN_DESC(90, "sdio1_wp_n", 1, 0x18, 24), |
| 171 | CYGNUS_PIN_DESC(91, "sdio1_card_rst", 1, 0x14, 10), |
| 172 | CYGNUS_PIN_DESC(92, "sdio1_led_on", 1, 0x18, 26), |
| 173 | CYGNUS_PIN_DESC(93, "sdio1_cd", 1, 0x14, 8), |
| 174 | CYGNUS_PIN_DESC(94, "sdio0_clk_sdcard", 1, 0x14, 26), |
| 175 | CYGNUS_PIN_DESC(95, "sdio0_cmd", 1, 0x14, 24), |
| 176 | CYGNUS_PIN_DESC(96, "sdio0_data0", 1, 0x14, 22), |
| 177 | CYGNUS_PIN_DESC(97, "sdio0_data1", 1, 0x14, 20), |
| 178 | CYGNUS_PIN_DESC(98, "sdio0_data2", 1, 0x14, 18), |
| 179 | CYGNUS_PIN_DESC(99, "sdio0_data3", 1, 0x14, 16), |
| 180 | CYGNUS_PIN_DESC(100, "sdio0_wp_n", 1, 0x14, 12), |
| 181 | CYGNUS_PIN_DESC(101, "sdio0_card_rst", 1, 0x14, 30), |
| 182 | CYGNUS_PIN_DESC(102, "sdio0_led_on", 1, 0x14, 14), |
| 183 | CYGNUS_PIN_DESC(103, "sdio0_cd", 1, 0x14, 28), |
| 184 | CYGNUS_PIN_DESC(104, "sflash_clk", 1, 0x18, 22), |
| 185 | CYGNUS_PIN_DESC(105, "sflash_cs_l", 1, 0x18, 20), |
| 186 | CYGNUS_PIN_DESC(106, "sflash_mosi", 1, 0x18, 14), |
| 187 | CYGNUS_PIN_DESC(107, "sflash_miso", 1, 0x18, 16), |
| 188 | CYGNUS_PIN_DESC(108, "sflash_wp_n", 1, 0x18, 12), |
| 189 | CYGNUS_PIN_DESC(109, "sflash_hold_n", 1, 0x18, 18), |
| 190 | CYGNUS_PIN_DESC(110, "nand_ale", 1, 0xc, 30), |
| 191 | CYGNUS_PIN_DESC(111, "nand_ce0_l", 1, 0xc, 28), |
| 192 | CYGNUS_PIN_DESC(112, "nand_ce1_l", 1, 0xc, 26), |
| 193 | CYGNUS_PIN_DESC(113, "nand_cle", 1, 0xc, 24), |
| 194 | CYGNUS_PIN_DESC(114, "nand_dq0", 1, 0xc, 22), |
| 195 | CYGNUS_PIN_DESC(115, "nand_dq1", 1, 0xc, 20), |
| 196 | CYGNUS_PIN_DESC(116, "nand_dq2", 1, 0xc, 18), |
| 197 | CYGNUS_PIN_DESC(117, "nand_dq3", 1, 0xc, 16), |
| 198 | CYGNUS_PIN_DESC(118, "nand_dq4", 1, 0xc, 14), |
| 199 | CYGNUS_PIN_DESC(119, "nand_dq5", 1, 0xc, 12), |
| 200 | CYGNUS_PIN_DESC(120, "nand_dq6", 1, 0xc, 10), |
| 201 | CYGNUS_PIN_DESC(121, "nand_dq7", 1, 0xc, 8), |
| 202 | CYGNUS_PIN_DESC(122, "nand_rb_l", 1, 0xc, 6), |
| 203 | CYGNUS_PIN_DESC(123, "nand_re_l", 1, 0xc, 4), |
| 204 | CYGNUS_PIN_DESC(124, "nand_we_l", 1, 0xc, 2), |
| 205 | CYGNUS_PIN_DESC(125, "nand_wp_l", 1, 0xc, 0), |
| 206 | CYGNUS_PIN_DESC(126, "lcd_clac", 1, 0x4, 26), |
| 207 | CYGNUS_PIN_DESC(127, "lcd_clcp", 1, 0x4, 24), |
| 208 | CYGNUS_PIN_DESC(128, "lcd_cld0", 1, 0x4, 22), |
| 209 | CYGNUS_PIN_DESC(129, "lcd_cld1", 1, 0x4, 0), |
| 210 | CYGNUS_PIN_DESC(130, "lcd_cld10", 1, 0x4, 20), |
| 211 | CYGNUS_PIN_DESC(131, "lcd_cld11", 1, 0x4, 18), |
| 212 | CYGNUS_PIN_DESC(132, "lcd_cld12", 1, 0x4, 16), |
| 213 | CYGNUS_PIN_DESC(133, "lcd_cld13", 1, 0x4, 14), |
| 214 | CYGNUS_PIN_DESC(134, "lcd_cld14", 1, 0x4, 12), |
| 215 | CYGNUS_PIN_DESC(135, "lcd_cld15", 1, 0x4, 10), |
| 216 | CYGNUS_PIN_DESC(136, "lcd_cld16", 1, 0x4, 8), |
| 217 | CYGNUS_PIN_DESC(137, "lcd_cld17", 1, 0x4, 6), |
| 218 | CYGNUS_PIN_DESC(138, "lcd_cld18", 1, 0x4, 4), |
| 219 | CYGNUS_PIN_DESC(139, "lcd_cld19", 1, 0x4, 2), |
| 220 | CYGNUS_PIN_DESC(140, "lcd_cld2", 1, 0x8, 22), |
| 221 | CYGNUS_PIN_DESC(141, "lcd_cld20", 1, 0x8, 30), |
| 222 | CYGNUS_PIN_DESC(142, "lcd_cld21", 1, 0x8, 28), |
| 223 | CYGNUS_PIN_DESC(143, "lcd_cld22", 1, 0x8, 26), |
| 224 | CYGNUS_PIN_DESC(144, "lcd_cld23", 1, 0x8, 24), |
| 225 | CYGNUS_PIN_DESC(145, "lcd_cld3", 1, 0x8, 20), |
| 226 | CYGNUS_PIN_DESC(146, "lcd_cld4", 1, 0x8, 18), |
| 227 | CYGNUS_PIN_DESC(147, "lcd_cld5", 1, 0x8, 16), |
| 228 | CYGNUS_PIN_DESC(148, "lcd_cld6", 1, 0x8, 14), |
| 229 | CYGNUS_PIN_DESC(149, "lcd_cld7", 1, 0x8, 12), |
| 230 | CYGNUS_PIN_DESC(150, "lcd_cld8", 1, 0x8, 10), |
| 231 | CYGNUS_PIN_DESC(151, "lcd_cld9", 1, 0x8, 8), |
| 232 | CYGNUS_PIN_DESC(152, "lcd_clfp", 1, 0x8, 6), |
| 233 | CYGNUS_PIN_DESC(153, "lcd_clle", 1, 0x8, 4), |
| 234 | CYGNUS_PIN_DESC(154, "lcd_cllp", 1, 0x8, 2), |
| 235 | CYGNUS_PIN_DESC(155, "lcd_clpower", 1, 0x8, 0), |
| 236 | CYGNUS_PIN_DESC(156, "camera_vsync", 1, 0x4, 30), |
| 237 | CYGNUS_PIN_DESC(157, "camera_trigger", 1, 0x0, 0), |
| 238 | CYGNUS_PIN_DESC(158, "camera_strobe", 1, 0x0, 2), |
| 239 | CYGNUS_PIN_DESC(159, "camera_standby", 1, 0x0, 4), |
| 240 | CYGNUS_PIN_DESC(160, "camera_reset_n", 1, 0x0, 6), |
| 241 | CYGNUS_PIN_DESC(161, "camera_pixdata9", 1, 0x0, 8), |
| 242 | CYGNUS_PIN_DESC(162, "camera_pixdata8", 1, 0x0, 10), |
| 243 | CYGNUS_PIN_DESC(163, "camera_pixdata7", 1, 0x0, 12), |
| 244 | CYGNUS_PIN_DESC(164, "camera_pixdata6", 1, 0x0, 14), |
| 245 | CYGNUS_PIN_DESC(165, "camera_pixdata5", 1, 0x0, 16), |
| 246 | CYGNUS_PIN_DESC(166, "camera_pixdata4", 1, 0x0, 18), |
| 247 | CYGNUS_PIN_DESC(167, "camera_pixdata3", 1, 0x0, 20), |
| 248 | CYGNUS_PIN_DESC(168, "camera_pixdata2", 1, 0x0, 22), |
| 249 | CYGNUS_PIN_DESC(169, "camera_pixdata1", 1, 0x0, 24), |
| 250 | CYGNUS_PIN_DESC(170, "camera_pixdata0", 1, 0x0, 26), |
| 251 | CYGNUS_PIN_DESC(171, "camera_pixclk", 1, 0x0, 28), |
| 252 | CYGNUS_PIN_DESC(172, "camera_hsync", 1, 0x0, 30), |
| 253 | CYGNUS_PIN_DESC(173, "camera_pll_ref_clk", 0, 0, 0), |
| 254 | CYGNUS_PIN_DESC(174, "usb_id_indication", 0, 0, 0), |
| 255 | CYGNUS_PIN_DESC(175, "usb_vbus_indication", 0, 0, 0), |
| 256 | CYGNUS_PIN_DESC(176, "gpio0_3p3", 0, 0, 0), |
| 257 | CYGNUS_PIN_DESC(177, "gpio1_3p3", 0, 0, 0), |
| 258 | CYGNUS_PIN_DESC(178, "gpio2_3p3", 0, 0, 0), |
| 259 | CYGNUS_PIN_DESC(179, "gpio3_3p3", 0, 0, 0), |
| 260 | }; |
| 261 | |
| 262 | int cygnus_gpio_request_enable(void *priv, unsigned pin) |
| 263 | { |
| 264 | struct cygnus_pinctrl *pinctrl = (struct cygnus_pinctrl *)priv; |
| 265 | struct cygnus_gpio_mux *mux = &cygnus_pins[pin].gpio_mux; |
| 266 | u32 val; |
| 267 | |
| 268 | /* not all pins support GPIO pinmux override */ |
| 269 | if (!mux->is_supported) |
| 270 | return -ENOTSUPP; |
| 271 | |
| 272 | val = read32(pinctrl->base1 + mux->offset); |
| 273 | val |= 0x3 << mux->shift; |
| 274 | write32(pinctrl->base1 + mux->offset, val); |
| 275 | |
| 276 | printk(BIOS_INFO, "gpio request enable pin=%u offset=0x%x shift=%u\n", |
| 277 | pin, mux->offset, mux->shift); |
| 278 | |
| 279 | return 0; |
| 280 | } |
| 281 | |
| 282 | void cygnus_gpio_disable_free(void *priv, unsigned pin) |
| 283 | { |
| 284 | struct cygnus_pinctrl *pinctrl = (struct cygnus_pinctrl *)priv; |
| 285 | struct cygnus_gpio_mux *mux = &cygnus_pins[pin].gpio_mux; |
| 286 | u32 val; |
| 287 | |
| 288 | if (!mux->is_supported) |
| 289 | return; |
| 290 | |
| 291 | val = read32(pinctrl->base1 + mux->offset); |
| 292 | val &= ~(0x3 << mux->shift); |
| 293 | write32(pinctrl->base1 + mux->offset, val); |
| 294 | |
| 295 | printk(BIOS_INFO, "gpio disable free pin=%u offset=0x%x shift=%u\n", |
| 296 | pin, mux->offset, mux->shift); |
| 297 | } |
| 298 | |
| 299 | void *cygnus_pinmux_init() |
| 300 | { |
| 301 | return &pinctrl_data; |
| 302 | } |