Merge branch 'master' of git://git.denx.de/u-boot-sh
- Various pinctrl / gpio fixes for R-Car
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <dm/pinctrl.h>
|
||||
#include <errno.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/io.h>
|
||||
@@ -117,19 +118,17 @@ static int rcar_gpio_get_function(struct udevice *dev, unsigned offset)
|
||||
static int rcar_gpio_request(struct udevice *dev, unsigned offset,
|
||||
const char *label)
|
||||
{
|
||||
struct rcar_gpio_priv *priv = dev_get_priv(dev);
|
||||
struct udevice *pctldev;
|
||||
int ret;
|
||||
return pinctrl_gpio_request(dev, offset);
|
||||
}
|
||||
|
||||
ret = uclass_get_device(UCLASS_PINCTRL, 0, &pctldev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sh_pfc_config_mux_for_gpio(pctldev, priv->pfc_offset + offset);
|
||||
static int rcar_gpio_free(struct udevice *dev, unsigned offset)
|
||||
{
|
||||
return pinctrl_gpio_free(dev, offset);
|
||||
}
|
||||
|
||||
static const struct dm_gpio_ops rcar_gpio_ops = {
|
||||
.request = rcar_gpio_request,
|
||||
.free = rcar_gpio_free,
|
||||
.direction_input = rcar_gpio_direction_input,
|
||||
.direction_output = rcar_gpio_direction_output,
|
||||
.get_value = rcar_gpio_get_value,
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
#define CSR_OPS 0x0000000F
|
||||
#define CSR_OPS_CONFIG BIT(1)
|
||||
|
||||
#define APSR_TDM BIT(14)
|
||||
|
||||
#define TCCR_TSRQ0 BIT(0)
|
||||
|
||||
#define RFLR_RFL_MIN 0x05EE
|
||||
@@ -389,9 +391,14 @@ static int ravb_dmac_init(struct udevice *dev)
|
||||
/* FIFO size set */
|
||||
writel(0x00222210, eth->iobase + RAVB_REG_TGC);
|
||||
|
||||
/* Delay CLK: 2ns */
|
||||
if (pdata->max_speed == 1000)
|
||||
writel(BIT(14), eth->iobase + RAVB_REG_APSR);
|
||||
/* Delay CLK: 2ns (not applicable on R-Car E3/D3) */
|
||||
if ((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A77990) ||
|
||||
(rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A77995))
|
||||
return 0;
|
||||
|
||||
if ((pdata->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) ||
|
||||
(pdata->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID))
|
||||
writel(APSR_TDM, eth->iobase + RAVB_REG_APSR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -172,6 +172,102 @@ static int pinconfig_post_bind(struct udevice *dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
pinctrl_gpio_get_pinctrl_and_offset(struct udevice *dev, unsigned offset,
|
||||
struct udevice **pctldev,
|
||||
unsigned int *pin_selector)
|
||||
{
|
||||
struct ofnode_phandle_args args;
|
||||
unsigned gpio_offset, pfc_base, pfc_pins;
|
||||
int ret;
|
||||
|
||||
ret = dev_read_phandle_with_args(dev, "gpio-ranges", NULL, 3,
|
||||
0, &args);
|
||||
if (ret) {
|
||||
dev_dbg(dev, "%s: dev_read_phandle_with_args: err=%d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = uclass_get_device_by_ofnode(UCLASS_PINCTRL,
|
||||
args.node, pctldev);
|
||||
if (ret) {
|
||||
dev_dbg(dev,
|
||||
"%s: uclass_get_device_by_of_offset failed: err=%d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpio_offset = args.args[0];
|
||||
pfc_base = args.args[1];
|
||||
pfc_pins = args.args[2];
|
||||
|
||||
if (offset < gpio_offset || offset > gpio_offset + pfc_pins) {
|
||||
dev_dbg(dev,
|
||||
"%s: GPIO can not be mapped to pincontrol pin\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
offset -= gpio_offset;
|
||||
offset += pfc_base;
|
||||
*pin_selector = offset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinctrl_gpio_request() - request a single pin to be used as GPIO
|
||||
*
|
||||
* @dev: GPIO peripheral device
|
||||
* @offset: the GPIO pin offset from the GPIO controller
|
||||
* @return: 0 on success, or negative error code on failure
|
||||
*/
|
||||
int pinctrl_gpio_request(struct udevice *dev, unsigned offset)
|
||||
{
|
||||
const struct pinctrl_ops *ops;
|
||||
struct udevice *pctldev;
|
||||
unsigned int pin_selector;
|
||||
int ret;
|
||||
|
||||
ret = pinctrl_gpio_get_pinctrl_and_offset(dev, offset,
|
||||
&pctldev, &pin_selector);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ops = pinctrl_get_ops(pctldev);
|
||||
if (!ops || !ops->gpio_request_enable)
|
||||
return -ENOTSUPP;
|
||||
|
||||
return ops->gpio_request_enable(pctldev, pin_selector);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinctrl_gpio_free() - free a single pin used as GPIO
|
||||
*
|
||||
* @dev: GPIO peripheral device
|
||||
* @offset: the GPIO pin offset from the GPIO controller
|
||||
* @return: 0 on success, or negative error code on failure
|
||||
*/
|
||||
int pinctrl_gpio_free(struct udevice *dev, unsigned offset)
|
||||
{
|
||||
const struct pinctrl_ops *ops;
|
||||
struct udevice *pctldev;
|
||||
unsigned int pin_selector;
|
||||
int ret;
|
||||
|
||||
ret = pinctrl_gpio_get_pinctrl_and_offset(dev, offset,
|
||||
&pctldev, &pin_selector);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ops = pinctrl_get_ops(pctldev);
|
||||
if (!ops || !ops->gpio_disable_free)
|
||||
return -ENOTSUPP;
|
||||
|
||||
return ops->gpio_disable_free(pctldev, pin_selector);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinctrl_select_state_simple() - simple implementation of pinctrl_select_state
|
||||
*
|
||||
|
||||
@@ -459,7 +459,44 @@ static const char *sh_pfc_pinctrl_get_function_name(struct udevice *dev,
|
||||
return priv->pfc.info->functions[selector].name;
|
||||
}
|
||||
|
||||
int sh_pfc_config_mux_for_gpio(struct udevice *dev, unsigned pin_selector)
|
||||
static int sh_pfc_gpio_request_enable(struct udevice *dev,
|
||||
unsigned pin_selector)
|
||||
{
|
||||
struct sh_pfc_pinctrl_priv *priv = dev_get_priv(dev);
|
||||
struct sh_pfc_pinctrl *pmx = &priv->pmx;
|
||||
struct sh_pfc *pfc = &priv->pfc;
|
||||
struct sh_pfc_pin_config *cfg;
|
||||
const struct sh_pfc_pin *pin = NULL;
|
||||
int i, ret, idx;
|
||||
|
||||
for (i = 1; i < pfc->info->nr_pins; i++) {
|
||||
if (priv->pfc.info->pins[i].pin != pin_selector)
|
||||
continue;
|
||||
|
||||
pin = &priv->pfc.info->pins[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pin)
|
||||
return -EINVAL;
|
||||
|
||||
idx = sh_pfc_get_pin_index(pfc, pin->pin);
|
||||
cfg = &pmx->configs[idx];
|
||||
|
||||
if (cfg->type != PINMUX_TYPE_NONE)
|
||||
return -EBUSY;
|
||||
|
||||
ret = sh_pfc_config_mux(pfc, pin->enum_id, PINMUX_TYPE_GPIO);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cfg->type = PINMUX_TYPE_GPIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_pfc_gpio_disable_free(struct udevice *dev,
|
||||
unsigned pin_selector)
|
||||
{
|
||||
struct sh_pfc_pinctrl_priv *priv = dev_get_priv(dev);
|
||||
struct sh_pfc_pinctrl *pmx = &priv->pmx;
|
||||
@@ -482,10 +519,9 @@ int sh_pfc_config_mux_for_gpio(struct udevice *dev, unsigned pin_selector)
|
||||
idx = sh_pfc_get_pin_index(pfc, pin->pin);
|
||||
cfg = &pmx->configs[idx];
|
||||
|
||||
if (cfg->type != PINMUX_TYPE_NONE)
|
||||
return -EBUSY;
|
||||
cfg->type = PINMUX_TYPE_NONE;
|
||||
|
||||
return sh_pfc_config_mux(pfc, pin->enum_id, PINMUX_TYPE_GPIO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_pfc_pinctrl_pin_set(struct udevice *dev, unsigned pin_selector,
|
||||
@@ -746,6 +782,9 @@ static struct pinctrl_ops sh_pfc_pinctrl_ops = {
|
||||
.pinmux_set = sh_pfc_pinctrl_pin_set,
|
||||
.pinmux_group_set = sh_pfc_pinctrl_group_set,
|
||||
.set_state = pinctrl_generic_set_state,
|
||||
|
||||
.gpio_request_enable = sh_pfc_gpio_request_enable,
|
||||
.gpio_disable_free = sh_pfc_gpio_disable_free,
|
||||
};
|
||||
|
||||
static int sh_pfc_map_pins(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx)
|
||||
|
||||
@@ -275,7 +275,6 @@ void sh_pfc_write(struct sh_pfc *pfc, u32 reg, u32 data);
|
||||
const struct pinmux_bias_reg *
|
||||
sh_pfc_pin_to_bias_reg(const struct sh_pfc *pfc, unsigned int pin,
|
||||
unsigned int *bit);
|
||||
int sh_pfc_config_mux_for_gpio(struct udevice *dev, unsigned pin_selector);
|
||||
|
||||
extern const struct sh_pfc_soc_info r8a7790_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info r8a7791_pinmux_info;
|
||||
|
||||
Reference in New Issue
Block a user