diff --git a/firmware/SOURCES b/firmware/SOURCES index 4c1fa7bf46..10c9789069 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -1659,7 +1659,9 @@ target/mips/ingenic_x1000/pwm-x1000.c target/mips/ingenic_x1000/sfc-x1000.c target/mips/ingenic_x1000/system-x1000.c target/mips/ingenic_x1000/timer-x1000.c +#ifndef USB_NONE target/mips/ingenic_x1000/usb-x1000.c +#endif #if (CONFIG_STORAGE & (STORAGE_SD|STORAGE_MMC|STORAGE_ATA)) target/mips/ingenic_x1000/msc-x1000.c #endif diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c index 542d1745dc..8528b803f7 100644 --- a/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/audiohw-fiiom3k.c @@ -87,5 +87,5 @@ void audiohw_set_power_mode(int mode) void ak4376_set_pdn_pin(int level) { - gpio_config(GPIO_A, 1 << 16, GPIO_OUTPUT(level ? 1 : 0)); + gpio_set_level(GPIO_AK4376_POWER, level ? 1 : 0); } diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c index efc652c84f..47b5e3d6dc 100644 --- a/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/button-fiiom3k.c @@ -35,8 +35,6 @@ # include "font.h" #endif -#define FT_RST_PIN (1 << 15) -#define FT_INT_PIN (1 << 12) #define ft_interrupt GPIOB12 /* Touch event types */ @@ -389,11 +387,13 @@ static void ft_init(void) i2c_x1000_set_freq(FT6x06_BUS, I2C_FREQ_400K); /* Reset chip */ - gpio_config(GPIO_B, FT_RST_PIN|FT_INT_PIN, GPIO_OUTPUT(0)); + gpio_set_level(GPIO_FT6x06_RESET, 0); mdelay(5); - gpio_out_level(GPIO_B, FT_RST_PIN, 1); - gpio_config(GPIO_B, FT_INT_PIN, GPIO_IRQ_EDGE(0)); - gpio_enable_irq(GPIO_B, FT_INT_PIN); + gpio_set_level(GPIO_FT6x06_RESET, 1); + + /* Configure the interrupt pin */ + gpio_set_function(GPIO_FT6x06_INTERRUPT, GPIOF_IRQ_EDGE(0)); + gpio_enable_irq(GPIO_FT6x06_INTERRUPT); } void touchpad_set_sensitivity(int level) @@ -454,10 +454,6 @@ static void hp_detect_init(void) /* Rockbox interface */ void button_init_device(void) { - /* Configure physical button GPIOs */ - gpio_config(GPIO_A, (1 << 17) | (1 << 19), GPIO_INPUT); - gpio_config(GPIO_B, (1 << 28) | (1 << 31), GPIO_INPUT); - /* Initialize touchpad */ ft_init(); diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/gpio-target.h b/firmware/target/mips/ingenic_x1000/fiiom3k/gpio-target.h new file mode 100644 index 0000000000..f580cd9167 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/gpio-target.h @@ -0,0 +1,26 @@ +/* Name Port Pins Function */ +DEFINE_PINGROUP(LCD_DATA, GPIO_A, 0xffff << 0, GPIOF_DEVICE(1)) +DEFINE_PINGROUP(LCD_CONTROL, GPIO_B, 0x1a << 16, GPIOF_DEVICE(1)) +DEFINE_PINGROUP(MSC0, GPIO_A, 0x3f << 20, GPIOF_DEVICE(1)) +DEFINE_PINGROUP(SFC, GPIO_A, 0x3f << 26, GPIOF_DEVICE(1)) +DEFINE_PINGROUP(I2S, GPIO_B, 0x1f << 0, GPIOF_DEVICE(1)) +DEFINE_PINGROUP(DMIC, GPIO_B, 3 << 21, GPIOF_DEVICE(0)) +DEFINE_PINGROUP(I2C0, GPIO_B, 3 << 23, GPIOF_DEVICE(0)) +DEFINE_PINGROUP(I2C1, GPIO_C, 3 << 26, GPIOF_DEVICE(0)) +DEFINE_PINGROUP(I2C2, GPIO_D, 3 << 0, GPIOF_DEVICE(1)) + +/* Name Pin Function */ +DEFINE_GPIO(AK4376_POWER, GPIO_PA(16), GPIOF_OUTPUT(0)) +DEFINE_GPIO(BTN_PLAY, GPIO_PA(17), GPIOF_INPUT) +DEFINE_GPIO(BTN_VOL_UP, GPIO_PA(19), GPIOF_INPUT) +DEFINE_GPIO(MSC0_CD, GPIO_PB(6), GPIOF_INPUT) +DEFINE_GPIO(USB_ID, GPIO_PB(7), GPIOF_INPUT) +DEFINE_GPIO(AXP_IRQ, GPIO_PB(10), GPIOF_INPUT) +DEFINE_GPIO(USB_DETECT, GPIO_PB(11), GPIOF_INPUT) +DEFINE_GPIO(FT6x06_INTERRUPT, GPIO_PB(12), GPIOF_INPUT) +DEFINE_GPIO(FT6x06_RESET, GPIO_PB(15), GPIOF_OUTPUT(0)) +DEFINE_GPIO(LCD_RD, GPIO_PB(16), GPIOF_OUTPUT(1)) +DEFINE_GPIO(LCD_CE, GPIO_PB(18), GPIOF_OUTPUT(1)) +DEFINE_GPIO(USB_DRVVBUS, GPIO_PB(25), GPIOF_OUTPUT(0)) +DEFINE_GPIO(BTN_VOL_DOWN, GPIO_PB(28), GPIOF_INPUT) +DEFINE_GPIO(BTN_POWER, GPIO_PB(31), GPIOF_INPUT) diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/lcd-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/lcd-fiiom3k.c index 96f794d7df..29e72286ff 100644 --- a/firmware/target/mips/ingenic_x1000/fiiom3k/lcd-fiiom3k.c +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/lcd-fiiom3k.c @@ -25,9 +25,6 @@ #include "gpio-x1000.h" #include "system.h" -#define CS_PIN (1 << 18) -#define RD_PIN (1 << 16) - static const uint32_t fiio_lcd_cmd_enable[] = { /* Software reset */ LCD_INSTR_CMD, 0x01, @@ -169,17 +166,27 @@ const struct lcd_tgt_config lcd_tgt_config = { void lcd_tgt_enable(bool enable) { if(enable) { - gpio_config(GPIO_A, 0xffff, GPIO_DEVICE(1)); - gpio_config(GPIO_B, 0x1f << 16, GPIO_DEVICE(1)); - gpio_config(GPIO_B, CS_PIN|RD_PIN, GPIO_OUTPUT(1)); + /* reset controller, probably */ + gpio_set_level(GPIO_LCD_CE, 1); + gpio_set_level(GPIO_LCD_RD, 1); mdelay(5); - gpio_out_level(GPIO_B, CS_PIN, 0); + gpio_set_level(GPIO_LCD_CE, 0); + + /* set the clock whatever it is... */ lcd_set_clock(X1000_CLK_SCLK_A, 30000000); + + /* program the initial configuration */ lcd_exec_commands(&fiio_lcd_cmd_enable[0]); } else { + /* go to sleep mode first */ lcd_exec_commands(&fiio_lcd_cmd_sleep[0]); - mdelay(115); /* ensure we wait a total of 120ms before power off */ - gpio_config(GPIO_B, CS_PIN|RD_PIN, 0); + + /* ensure we wait a total of 120ms before power off */ + mdelay(115); + + /* this is intended to power off the panel but I'm not sure it does */ + gpio_set_level(GPIO_LCD_CE, 0); + gpio_set_level(GPIO_LCD_RD, 0); } } diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c index a7f6165980..6b1ad2dbb5 100644 --- a/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c @@ -28,7 +28,6 @@ #endif #include "axp-pmu.h" #include "i2c-x1000.h" -#include "gpio-x1000.h" const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = { @@ -53,9 +52,6 @@ const unsigned short percent_to_volt_charge[11] = 3485, 3780, 3836, 3857, 3890, 3930, 3986, 4062, 4158, 4185, 4196 }; -#define AXP_IRQ_PORT GPIO_B -#define AXP_IRQ_PIN (1 << 10) - void power_init(void) { /* Initialize driver */ diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c index efea5aa323..85ce4da8f6 100644 --- a/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c @@ -116,7 +116,7 @@ int spl_get_boot_option(void) const int max_iter_count = 30; /* Configure the button GPIOs as inputs */ - gpio_config(GPIO_A, pinmask, GPIO_INPUT); + gpioz_configure(GPIO_A, pinmask, GPIOF_INPUT); /* Poll the pins for a short duration to detect a keypress */ do { diff --git a/firmware/target/mips/ingenic_x1000/gpio-x1000.c b/firmware/target/mips/ingenic_x1000/gpio-x1000.c index 40e4c5e631..14195359df 100644 --- a/firmware/target/mips/ingenic_x1000/gpio-x1000.c +++ b/firmware/target/mips/ingenic_x1000/gpio-x1000.c @@ -20,37 +20,91 @@ ****************************************************************************/ #include "gpio-x1000.h" -#include "kernel.h" + +const struct gpio_setting gpio_settings[PIN_COUNT] = { +#define DEFINE_GPIO(_name, _gpio, _func) \ + {.gpio = _gpio, .func = _func}, +#define DEFINE_PINGROUP(...) +#include "gpio-target.h" +#undef DEFINE_GPIO +#undef DEFINE_PINGROUP +}; + +const struct pingroup_setting pingroup_settings[PINGROUP_COUNT] = { +#define DEFINE_GPIO(...) +#define DEFINE_PINGROUP(_name, _port, _pins, _func) \ + {.port = _port, .pins = _pins, .func = _func}, +#include "gpio-target.h" +#undef DEFINE_GPIO +#undef DEFINE_PINGROUP +}; + +const char* const gpio_names[PIN_COUNT] = { +#define DEFINE_GPIO(_name, ...) #_name, +#define DEFINE_PINGROUP(...) +#include "gpio-target.h" +#undef DEFINE_GPIO +#undef DEFINE_PINGROUP +}; + +const char* const pingroup_names[PINGROUP_COUNT] = { +#define DEFINE_GPIO(...) +#define DEFINE_PINGROUP(_name, ...) #_name, +#include "gpio-target.h" +#undef DEFINE_GPIO +#undef DEFINE_PINGROUP +}; void gpio_init(void) { + /* Apply all initial GPIO settings */ + for(int i = 0; i < PINGROUP_COUNT; ++i) { + const struct pingroup_setting* d = &pingroup_settings[i]; + if(d->pins != 0) + gpioz_configure(d->port, d->pins, d->func); + } + + for(int i = 0; i < PIN_COUNT; ++i) { + const struct gpio_setting* d = &gpio_settings[i]; + if(d->gpio != GPIO_NONE) + gpioz_configure(GPION_PORT(d->gpio), GPION_MASK(d->gpio), d->func); + } + /* Any GPIO pins left in an IRQ trigger state need to be switched off, * because the drivers won't be ready to handle the interrupts until they * get initialized later in the boot. */ for(int i = 0; i < 4; ++i) { uint32_t intbits = REG_GPIO_INT(i); if(intbits) { - gpio_config(i, intbits, GPIO_INPUT); + gpioz_configure(i, intbits, GPIOF_INPUT); jz_clr(GPIO_FLAG(i), intbits); } } } -void gpio_config(int port, unsigned pinmask, int func) +void gpioz_configure(int port, uint32_t pins, int func) { - unsigned intr = REG_GPIO_INT(port); - unsigned mask = REG_GPIO_MSK(port); - unsigned pat1 = REG_GPIO_PAT1(port); - unsigned pat0 = REG_GPIO_PAT0(port); + uint32_t intr = REG_GPIO_INT(port); + uint32_t mask = REG_GPIO_MSK(port); + uint32_t pat1 = REG_GPIO_PAT1(port); + uint32_t pat0 = REG_GPIO_PAT0(port); - if(func & 8) jz_set(GPIO_INT(GPIO_Z), (intr & pinmask) ^ pinmask); - else jz_clr(GPIO_INT(GPIO_Z), (~intr & pinmask) ^ pinmask); - if(func & 4) jz_set(GPIO_MSK(GPIO_Z), (mask & pinmask) ^ pinmask); - else jz_clr(GPIO_MSK(GPIO_Z), (~mask & pinmask) ^ pinmask); - if(func & 2) jz_set(GPIO_PAT1(GPIO_Z), (pat1 & pinmask) ^ pinmask); - else jz_clr(GPIO_PAT1(GPIO_Z), (~pat1 & pinmask) ^ pinmask); - if(func & 1) jz_set(GPIO_PAT0(GPIO_Z), (pat0 & pinmask) ^ pinmask); - else jz_clr(GPIO_PAT0(GPIO_Z), (~pat0 & pinmask) ^ pinmask); + /* Note: GPIO Z has _only_ set and clear registers, which are used to + * atomically manipulate the selected GPIO port when we write GID2LD. + * So there's not really any direct setting or clearing going on here... + */ + if(func & GPIO_F_INT) jz_set(GPIO_INT(GPIO_Z), (intr & pins) ^ pins); + else jz_clr(GPIO_INT(GPIO_Z), (~intr & pins) ^ pins); + if(func & GPIO_F_MASK) jz_set(GPIO_MSK(GPIO_Z), (mask & pins) ^ pins); + else jz_clr(GPIO_MSK(GPIO_Z), (~mask & pins) ^ pins); + if(func & GPIO_F_PAT1) jz_set(GPIO_PAT1(GPIO_Z), (pat1 & pins) ^ pins); + else jz_clr(GPIO_PAT1(GPIO_Z), (~pat1 & pins) ^ pins); + if(func & GPIO_F_PAT0) jz_set(GPIO_PAT0(GPIO_Z), (pat0 & pins) ^ pins); + else jz_clr(GPIO_PAT0(GPIO_Z), (~pat0 & pins) ^ pins); REG_GPIO_Z_GID2LD = port; - gpio_set_pull(port, pinmask, func & 16); + + if(func & GPIO_F_PULL) + jz_set(GPIO_PULL(port), pins); + else + jz_clr(GPIO_PULL(port), pins); } diff --git a/firmware/target/mips/ingenic_x1000/gpio-x1000.h b/firmware/target/mips/ingenic_x1000/gpio-x1000.h index cfbe86338a..5d147fc18f 100644 --- a/firmware/target/mips/ingenic_x1000/gpio-x1000.h +++ b/firmware/target/mips/ingenic_x1000/gpio-x1000.h @@ -22,33 +22,6 @@ #ifndef __GPIO_X1000_H__ #define __GPIO_X1000_H__ -/* GPIO API - * -------- - * - * To assign a new function to a GPIO, call gpio_config(). This uses the - * hardware's GPIO Z facility to atomically set most GPIO registers at once, - * so it can be used to make any state transition safely. Since GPIO Z is - * a global hardware resource, it is unsafe to call gpio_config() from IRQ - * context -- if the interrupted code was also running gpio_config(), then - * the results would be unpredictable. - * - * Depending on the current GPIO state, certain state transitions are safe to - * perform without locking, as they only change one register: - * - * - for pins in GPIO_OUTPUT state: - * - use gpio_out_level() to change the output level - * - * - for pins in GPIO_IRQ_LEVEL or GPIO_IRQ_EDGE state: - * - use gpio_irq_level() to change the trigger level - * - use gpio_irq_mask() to mask/unmask the IRQ - * - * - for pins in GPIO_DEVICE or GPIO_INPUT state: - * - no special transitions allowed - * - * - in all states: - * - use gpio_set_pull() to change the pull-up/pull-down state - */ - #include "x1000/gpio.h" /* GPIO port numbers */ @@ -66,42 +39,137 @@ #define GPIO_F_PAT0 1 /* GPIO function numbers */ -#define GPIO_DEVICE(i) ((i)&3) -#define GPIO_OUTPUT(i) (0x4|((i)&1)) -#define GPIO_INPUT 0x16 -#define GPIO_IRQ_LEVEL(i) (0x1c|((i)&1)) -#define GPIO_IRQ_EDGE(i) (0x1e|((i)&1)) +#define GPIOF_DEVICE(i) ((i)&3) +#define GPIOF_OUTPUT(i) (0x4|((i)&1)) +#define GPIOF_INPUT 0x16 +#define GPIOF_IRQ_LEVEL(i) (0x1c|((i)&1)) +#define GPIOF_IRQ_EDGE(i) (0x1e|((i)&1)) +/* GPIO pin numbers */ +#define GPION_CREATE(port, pin) ((((port) & 3) << 5) | ((pin) & 0x1f)) +#define GPION_PORT(gpio) (((gpio) >> 5) & 3) +#define GPION_PIN(gpio) ((gpio) & 0x1f) +#define GPION_MASK(gpio) (1u << GPION_PIN(gpio)) + +/* Easy pin number macros */ +#define GPIO_PA(x) GPION_CREATE(GPIO_A, x) +#define GPIO_PB(x) GPION_CREATE(GPIO_B, x) +#define GPIO_PC(x) GPION_CREATE(GPIO_C, x) +#define GPIO_PD(x) GPION_CREATE(GPIO_D, x) + +/* Pingroup settings are used for system devices */ +struct pingroup_setting { + int port; + uint32_t pins; + int func; +}; + +/* GPIO settings are used for single pins under software control */ +struct gpio_setting { + int gpio; + int func; +}; + +/* Target pins are defined as GPIO_XXX constants usable with the GPIO API */ +enum { +#define DEFINE_GPIO(_name, _gpio, _func) GPIO_##_name = _gpio, +#define DEFINE_PINGROUP(...) +#include "gpio-target.h" +#undef DEFINE_GPIO +#undef DEFINE_PINGROUP + GPIO_NONE = -1, +}; + +/* These are pin IDs which index gpio_settings */ +enum { +#define DEFINE_GPIO(_name, ...) PIN_##_name, +#define DEFINE_PINGROUP(...) +#include "gpio-target.h" +#undef DEFINE_GPIO +#undef DEFINE_PINGROUP + PIN_COUNT, +}; + +/* Pingroup IDs which index pingroup_settings */ +enum { +#define DEFINE_GPIO(...) +#define DEFINE_PINGROUP(_name, ...) PINGROUP_##_name, +#include "gpio-target.h" +#undef DEFINE_GPIO +#undef DEFINE_PINGROUP + PINGROUP_COUNT, +}; + +/* arrays which define the target's GPIO settings */ +extern const struct gpio_setting gpio_settings[PIN_COUNT]; +extern const struct pingroup_setting pingroup_settings[PINGROUP_COUNT]; + +/* stringified names for use in debug menus */ +extern const char* const gpio_names[PIN_COUNT]; +extern const char* const pingroup_names[PINGROUP_COUNT]; + +/* called at early init to set up GPIOs */ extern void gpio_init(void); -extern void gpio_config(int port, unsigned pinmask, int func); -static inline void gpio_out_level(int port, unsigned pinmask, int level) +/* Use GPIO Z to reconfigure several pins atomically */ +extern void gpioz_configure(int port, uint32_t pins, int func); + +static inline void gpio_set_function(int gpio, int func) { - if(level) - jz_set(GPIO_PAT0(port), pinmask); - else - jz_clr(GPIO_PAT0(port), pinmask); + gpioz_configure(GPION_PORT(gpio), GPION_MASK(gpio), func); } -#define gpio_irq_level gpio_out_level - -static inline void gpio_irq_mask(int port, unsigned pinmask, int masked) +static inline int gpio_get_level(int gpio) { - if(masked) - jz_set(GPIO_MSK(port), pinmask); - else - jz_clr(GPIO_MSK(port), pinmask); + return REG_GPIO_PIN(GPION_PORT(gpio)) & GPION_MASK(gpio) ? 1 : 0; } -#define gpio_enable_irq(port, pinmask) gpio_irq_mask((port), (pinmask), 0) -#define gpio_disable_irq(port, pinmask) gpio_irq_mask((port), (pinmask), 1) +static inline void gpio_set_level(int gpio, int value) +{ + if(value) + jz_set(GPIO_PAT0(GPION_PORT(gpio)), GPION_MASK(gpio)); + else + jz_clr(GPIO_PAT0(GPION_PORT(gpio)), GPION_MASK(gpio)); +} -static inline void gpio_set_pull(int port, unsigned pinmask, int state) +static inline void gpio_set_pull(int gpio, int state) { if(state) - jz_set(GPIO_PULL(port), pinmask); + jz_set(GPIO_PULL(GPION_PORT(gpio)), GPION_MASK(gpio)); else - jz_clr(GPIO_PULL(port), pinmask); + jz_clr(GPIO_PULL(GPION_PORT(gpio)), GPION_MASK(gpio)); +} + +static inline void gpio_mask_irq(int gpio, int mask) +{ + if(mask) + jz_set(GPIO_MSK(GPION_PORT(gpio)), GPION_MASK(gpio)); + else + jz_clr(GPIO_MSK(GPION_PORT(gpio)), GPION_MASK(gpio)); +} + +#define gpio_set_irq_level gpio_set_level +#define gpio_enable_irq(gpio) gpio_mask_irq((gpio), 0) +#define gpio_disable_irq(gpio) gpio_mask_irq((gpio), 1) + +/* Helper function for edge-triggered IRQs when you want to get an + * interrupt on both the rising and falling edges. The hardware can + * only be set up to interrupt on one edge, so interrupt handlers + * can call this function to flip the trigger to the other edge. + * + * Despite the name, this doesn't depend on the currently set edge, + * it just reads the GPIO state and sets up an edge trigger to detect + * a change to the other state -- if some transitions were missed the + * IRQ trigger may remain unchanged. + * + * It can be safely used to initialize the IRQ level. + */ +static inline void gpio_flip_edge_irq(int gpio) +{ + if(gpio_get_level(gpio)) + gpio_set_irq_level(gpio, 0); + else + gpio_set_irq_level(gpio, 1); } #endif /* __GPIO_X1000_H__ */ diff --git a/firmware/target/mips/ingenic_x1000/i2c-x1000.c b/firmware/target/mips/ingenic_x1000/i2c-x1000.c index 8bf606227b..6a5d2e08d2 100644 --- a/firmware/target/mips/ingenic_x1000/i2c-x1000.c +++ b/firmware/target/mips/ingenic_x1000/i2c-x1000.c @@ -25,7 +25,6 @@ #include "kernel.h" #include "panic.h" #include "logf.h" -#include "gpio-x1000.h" #include "clk-x1000.h" #include "irq-x1000.h" #include "x1000/i2c.h" @@ -375,18 +374,6 @@ void i2c_init(void) /* Stuff only required during initialization is below, basically the same as * the old driver except for how the IRQs are initially set up. */ -static const struct { - int port; - unsigned pins; - int func; -} i2c_x1000_gpio_data[] = { - {GPIO_B, 3 << 23, GPIO_DEVICE(0)}, - {GPIO_C, 3 << 26, GPIO_DEVICE(0)}, - /* Note: I2C1 is also on the following pins (normally used by LCD) */ - /* {GPIO_A, 3 << 0, GPIO_DEVICE(2)}, */ - {GPIO_D, 3 << 0, GPIO_DEVICE(1)}, -}; - static void i2c_x1000_gate(int chn, int gate) { switch(chn) { @@ -468,11 +455,6 @@ void i2c_x1000_set_freq(int chn, int freq) jz_write(I2C_FHCNT(chn), t_HIGH); } - /* Claim pins */ - gpio_config(i2c_x1000_gpio_data[chn].port, - i2c_x1000_gpio_data[chn].pins, - i2c_x1000_gpio_data[chn].func); - /* Enable the controller */ i2c_x1000_enable(chn); } diff --git a/firmware/target/mips/ingenic_x1000/msc-x1000.c b/firmware/target/mips/ingenic_x1000/msc-x1000.c index b8f23053dc..92b3d4206a 100644 --- a/firmware/target/mips/ingenic_x1000/msc-x1000.c +++ b/firmware/target/mips/ingenic_x1000/msc-x1000.c @@ -48,7 +48,8 @@ static const msc_config msc_configs[] = { .msc_type = MSC_TYPE_SD, .bus_width = 4, .label = "microSD", - .cd_gpio = {GPIO_B, 1 << 6, 0}, + .cd_gpio = GPIO_MSC0_CD, + .cd_active_level = 0, }, #else # error "Please add X1000 MSC config" @@ -117,40 +118,14 @@ static void msc_init_one(msc_drv* d, int msc) msc_full_reset(d); system_enable_irq(msc == 0 ? IRQ_MSC0 : IRQ_MSC1); - /* Configure bus pins */ - int port, device; - unsigned pins; - if(msc == 0) { - port = GPIO_A; - device = 1; - switch(d->config->bus_width) { - case 8: pins = 0x3ff << 16; break; - case 4: pins = 0x03f << 20; break; - case 1: pins = 0x007 << 23; break; - default: pins = 0; break; - } - } else { - port = GPIO_C; - device = 0; - switch(d->config->bus_width) { - case 4: pins = 0x3f; break; - case 1: pins = 0x07; break; - default: pins = 0; break; - } - } - - gpio_config(port, pins, GPIO_DEVICE(device)); - /* Setup the card detect IRQ */ - if(d->config->cd_gpio.pin) { - port = d->config->cd_gpio.port; - pins = d->config->cd_gpio.pin; - int level = (REG_GPIO_PIN(port) & pins) ? 1 : 0; - if(level != d->config->cd_gpio.active_level) + if(d->config->cd_gpio != GPIO_NONE) { + if(gpio_get_level(d->config->cd_gpio) != d->config->cd_active_level) d->card_present = 0; - gpio_config(port, pins, GPIO_IRQ_EDGE(level ? 0 : 1)); - gpio_enable_irq(port, pins); + gpio_set_function(d->config->cd_gpio, GPIOF_IRQ_EDGE(1)); + gpio_flip_edge_irq(d->config->cd_gpio); + gpio_enable_irq(d->config->cd_gpio); } } @@ -212,12 +187,10 @@ void msc_full_reset(msc_drv* d) bool msc_card_detect(msc_drv* d) { - if(!d->config->cd_gpio.pin) + if(d->config->cd_gpio == GPIO_NONE) return true; - int l = REG_GPIO_PIN(d->config->cd_gpio.port) & d->config->cd_gpio.pin; - l = l ? 1 : 0; - return l == d->config->cd_gpio.active_level; + return gpio_get_level(d->config->cd_gpio) == d->config->cd_active_level; } /* --------------------------------------------------------------------------- @@ -661,7 +634,7 @@ static void msc_cd_interrupt(msc_drv* d) } /* Invert the IRQ */ - REG_GPIO_PAT0(d->config->cd_gpio.port) ^= d->config->cd_gpio.pin; + gpio_flip_edge_irq(d->config->cd_gpio); } void MSC0(void) diff --git a/firmware/target/mips/ingenic_x1000/msc-x1000.h b/firmware/target/mips/ingenic_x1000/msc-x1000.h index 53a5b301f0..70f67a70d6 100644 --- a/firmware/target/mips/ingenic_x1000/msc-x1000.h +++ b/firmware/target/mips/ingenic_x1000/msc-x1000.h @@ -83,18 +83,13 @@ #define MSC_SPEED_FAST 25000000 #define MSC_SPEED_HIGH 50000000 -typedef struct msc_gpio_data { - int port; - int pin; - int active_level; -} msc_gpio_data; - typedef struct msc_config { int msc_nr; int msc_type; int bus_width; const char* label; - struct msc_gpio_data cd_gpio; + int cd_gpio; + int cd_active_level; } msc_config; typedef struct msc_req { diff --git a/firmware/target/mips/ingenic_x1000/pcm-x1000.c b/firmware/target/mips/ingenic_x1000/pcm-x1000.c index fd5e9d20c8..a3da3411f2 100644 --- a/firmware/target/mips/ingenic_x1000/pcm-x1000.c +++ b/firmware/target/mips/ingenic_x1000/pcm-x1000.c @@ -28,7 +28,6 @@ #include "panic.h" #include "dma-x1000.h" #include "irq-x1000.h" -#include "gpio-x1000.h" #include "x1000/aic.h" #include "x1000/cpm.h" @@ -55,7 +54,6 @@ void pcm_play_dma_init(void) * on Ingenic's datasheets but I'm not sure what they are. Probably safe to * assume they are not useful to Rockbox... */ jz_writef(CPM_CLKGR, AIC(0)); - gpio_config(GPIO_B, 0x1f, GPIO_DEVICE(1)); /* Configure AIC with some sane defaults */ jz_writef(AIC_CFG, RST(1)); diff --git a/firmware/target/mips/ingenic_x1000/pwm-x1000.c b/firmware/target/mips/ingenic_x1000/pwm-x1000.c index 8530a38af5..e8243a42ce 100644 --- a/firmware/target/mips/ingenic_x1000/pwm-x1000.c +++ b/firmware/target/mips/ingenic_x1000/pwm-x1000.c @@ -26,12 +26,6 @@ #include "kernel.h" #include "x1000/tcu.h" -struct pwm_gpio_data { - int port; - unsigned pin; - int func; -}; - struct pwm_state { int period_ns; int duty_ns; @@ -40,14 +34,6 @@ struct pwm_state { int prescaler; }; -static const struct pwm_gpio_data pwm_gpios[] = { - {GPIO_C, 1 << 25, GPIO_DEVICE(0)}, - {GPIO_C, 1 << 26, GPIO_DEVICE(1)}, - {GPIO_C, 1 << 27, GPIO_DEVICE(1)}, - {GPIO_B, 1 << 6, GPIO_DEVICE(2)}, - {GPIO_C, 1 << 24, GPIO_DEVICE(0)}, -}; - static struct pwm_state pwm_state[] = { {-1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1}, @@ -56,6 +42,22 @@ static struct pwm_state pwm_state[] = { {-1, -1, -1, -1, -1}, }; +static const int pwm_gpio[] = { + GPIO_PC(25), + GPIO_PC(26), + GPIO_PC(27), + GPIO_PB(6), + GPIO_PC(24), +}; + +static const int pwm_gpio_func[] = { + GPIOF_DEVICE(0), + GPIOF_DEVICE(1), + GPIOF_DEVICE(1), + GPIOF_DEVICE(2), + GPIOF_DEVICE(0), +}; + void pwm_init(int chn) { /* clear cached state */ @@ -67,8 +69,7 @@ void pwm_init(int chn) st->prescaler = -1; /* clear GPIO and disable timer */ - const struct pwm_gpio_data* pg = &pwm_gpios[chn]; - gpio_config(pg->port, pg->pin, GPIO_OUTPUT(0)); + gpio_set_function(pwm_gpio[chn], GPIOF_OUTPUT(0)); jz_clr(TCU_STOP, 1 << chn); jz_clr(TCU_ENABLE, 1 << chn); jz_set(TCU_STOP, 1 << chn); @@ -161,15 +162,13 @@ void pwm_enable(int chn) jz_set(TCU_ENABLE, 1 << chn); /* Configure GPIO function */ - const struct pwm_gpio_data* pg = &pwm_gpios[chn]; - gpio_config(pg->port, pg->pin, pg->func); + gpio_set_function(pwm_gpio[chn], pwm_gpio_func[chn]); } void pwm_disable(int chn) { /* Set GPIO to output 0 */ - const struct pwm_gpio_data* pg = &pwm_gpios[chn]; - gpio_config(pg->port, pg->pin, GPIO_OUTPUT(0)); + gpio_set_function(pwm_gpio[chn], GPIOF_OUTPUT(0)); /* Stop timer */ jz_clr(TCU_ENABLE, 1 << chn); diff --git a/firmware/target/mips/ingenic_x1000/sd-x1000.c b/firmware/target/mips/ingenic_x1000/sd-x1000.c index 7fba617ce3..679a25a222 100644 --- a/firmware/target/mips/ingenic_x1000/sd-x1000.c +++ b/firmware/target/mips/ingenic_x1000/sd-x1000.c @@ -23,6 +23,7 @@ #include "sdmmc.h" #include "sd.h" #include "msc-x1000.h" +#include "gpio-x1000.h" #include /* #define LOGF_ENABLE */ @@ -201,7 +202,7 @@ bool sd_removable(IF_MD_NONVOID(int drive)) if(drive < 0) return false; - return sd_to_msc[IF_MD_DRV(drive)]->config->cd_gpio.pin != 0; + return sd_to_msc[IF_MD_DRV(drive)]->config->cd_gpio != GPIO_NONE; } #ifndef CONFIG_STORAGE_MULTI diff --git a/firmware/target/mips/ingenic_x1000/sfc-x1000.c b/firmware/target/mips/ingenic_x1000/sfc-x1000.c index 3f1cb25f07..c1ffb6a5e1 100644 --- a/firmware/target/mips/ingenic_x1000/sfc-x1000.c +++ b/firmware/target/mips/ingenic_x1000/sfc-x1000.c @@ -23,7 +23,6 @@ #include "kernel.h" #include "panic.h" #include "sfc-x1000.h" -#include "gpio-x1000.h" #include "irq-x1000.h" #include "x1000/sfc.h" #include "x1000/cpm.h" @@ -75,7 +74,6 @@ void sfc_unlock(void) void sfc_open(void) { - gpio_config(GPIO_A, 0x3f << 26, GPIO_DEVICE(1)); jz_writef(CPM_CLKGR, SFC(0)); jz_writef(SFC_GLB, OP_MODE_V(SLAVE), PHASE_NUM(1), THRESHOLD(FIFO_THRESH), WP_EN(1)); diff --git a/firmware/target/mips/ingenic_x1000/usb-x1000.c b/firmware/target/mips/ingenic_x1000/usb-x1000.c index 32413b0b94..1cedac4fa7 100644 --- a/firmware/target/mips/ingenic_x1000/usb-x1000.c +++ b/firmware/target/mips/ingenic_x1000/usb-x1000.c @@ -29,20 +29,9 @@ #include "x1000/cpm.h" #ifdef FIIO_M3K -# define USB_DETECT_PORT GPIO_B -# define USB_DETECT_PIN (1 << 11) -# define USB_DETECT_PIN_INT GPIOB11 -# define USB_ID_PORT GPIO_B -# define USB_ID_PIN (1 << 7) -#else -# ifndef USB_NONE -# error "please add USB GPIO pins" -# endif +# define USB_DETECT_PIN_INT GPIOB11 // TODO remove me #endif -#define USB_DRVVBUS_PORT GPIO_B -#define USB_DRVVBUS_PIN (1 << 25) - /* * USB-Designware driver API */ @@ -165,7 +154,8 @@ static volatile int usb_status = USB_EXTRACTED; static int __usb_detect(void) { - if(REG_GPIO_PIN(USB_DETECT_PORT) & USB_DETECT_PIN) + /* XXX: Do we need an active level define for this? */ + if(gpio_get_level(GPIO_USB_DETECT)) return USB_INSERTED; else return USB_EXTRACTED; @@ -183,7 +173,7 @@ void usb_init_device(void) { /* Disable drvvbus pin -- it is only used when acting as a host, * which Rockbox does not support */ - gpio_config(USB_DRVVBUS_PORT, USB_DRVVBUS_PIN, GPIO_OUTPUT(0)); + gpio_set_function(GPIO_USB_DRVVBUS, GPIOF_OUTPUT(0)); /* Power up the core clocks to allow writing to some registers needed to power it down */ @@ -194,9 +184,9 @@ void usb_init_device(void) #ifdef USB_STATUS_BY_EVENT /* Setup USB detect pin IRQ */ usb_status = __usb_detect(); - int level = (REG_GPIO_PIN(USB_DETECT_PORT) & USB_DETECT_PIN) ? 1 : 0; - gpio_config(USB_DETECT_PORT, USB_DETECT_PIN, GPIO_IRQ_EDGE(level ? 0 : 1)); - gpio_enable_irq(USB_DETECT_PORT, USB_DETECT_PIN); + gpio_set_function(GPIO_USB_DETECT, GPIOF_IRQ_EDGE(1)); + gpio_flip_edge_irq(GPIO_USB_DETECT); + gpio_enable_irq(GPIO_USB_DETECT); #endif } @@ -215,7 +205,7 @@ void USB_DETECT_PIN_INT(void) { /* Update status and flip the IRQ trigger edge */ usb_status = __usb_detect(); - REG_GPIO_PAT0(USB_DETECT_PORT) ^= USB_DETECT_PIN; + gpio_flip_edge_irq(GPIO_USB_DETECT); /* Notify Rockbox of event */ usb_status_event(usb_status);