x1000: GPIO refactor

The GPIO API was pretty clunky and pin settings were decentralized,
making it hard to see what was happening and making GPIO stuff look
like a mess, frankly.

Instead of passing clunky (port, pin) pairs everywhere, GPIOs are now
identified with a single int. The extra overhead should be minimal as
GPIO configuration is generally not on a performance-critical path.

Pin assignments are now mostly consolidated in gpio-target.h and put
in various tables so gpio_init() can assign most pins at boot time.

Most drivers no longer need to touch GPIOs and basic pin I/O stuff
can happen without config since pins are put into the right state.
IRQ pins still need to be configured manually before use.

Change-Id: Ic5326284b0b2a2f613e9e76a41cb50e24af3aa47
This commit is contained in:
Aidan MacDonald 2021-06-05 00:12:01 +01:00
parent 695d1701cd
commit e85bc74b30
17 changed files with 281 additions and 196 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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();

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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 */

View File

@ -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 {

View File

@ -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);
}

View File

@ -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__ */

View File

@ -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);
}

View File

@ -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)

View File

@ -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 {

View File

@ -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));

View File

@ -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);

View File

@ -23,6 +23,7 @@
#include "sdmmc.h"
#include "sd.h"
#include "msc-x1000.h"
#include "gpio-x1000.h"
#include <string.h>
/* #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

View File

@ -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));

View File

@ -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);