FSI changes for 5.10

- Misc code cleanups. Thanks to Colin, Xu and Rikard
 
  - Features for the ASPEED FSI master
   * Detect connection type and routing for Tacoma
   * Run at full speed (200MHz) by default
   * Set bus speed with a parameter
   * CFAM reset GPIO
   * 23 bit addressing
 
  - Core features
   * Disable unused links
   * Set LBUS ownership
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+nHMAt9PCBDH63wBa3ZZB4FHcJ4FAl9bBWwACgkQa3ZZB4FH
 cJ7Usg/9G1vnAnxHk5/nAaf6JCw1CS5UINQjsqV90tAuo3Ry62E5Nx4o+3XJx3Vv
 EfXh3xdRnm6y2di5BQ1mqcVU6il2V6dDWl6Q6uB09IHU+bZFdViqzxMlt/aWho7d
 Jm0YIcPjQqwA7vzO/FgFVNqYMFEhmfBlpG+Hb4E1fdPk2jfMipD8DhuVP5r42/bS
 HFuxt8HWrhgHwKzQEXu3n0WJxRbREKv7+TGGDD6DTX97pgNqlwyjeekhGoY7T26x
 LC2zVm+3n6DAt7Rm+Z4G61yh77jThAYjHE5OcOFV8C3KC+H3R6U35te6OtQ0vpws
 8GLTw6cN6SlBr9yjac5ajCH4zI5iFa9xfTECC2o+YuDYSZu+2hAdBGzTUd3FrKQw
 XN5940K2ZDPQcltMiY0OY14O9ynb19KJPzVIBWoPfOo0ILgn6cmYZTP6WAmvzhob
 g5cvrafrH9LWEfXc8P6sD+VH246adCjqYXHSZMKs+zapc70jiThqhneHVkeG9nrt
 dPaqmY3NCt8DaCw7tYWODIBX6aCx//uC2Q1l7rqPUAXxzn04MY+YYL1T61O30Htq
 dXszfLTH/HouzVq4IMX47E+pZvIxvdjA4mVyMzvh4f/Oeu+jB3PFrzSCVX66Vtdp
 dGR75Gl1rdHkWRmZrkbILDj9S3VlQfIpLSSsAJWwOsYPSNVxgkQ=
 =pl/5
 -----END PGP SIGNATURE-----

Merge tag 'fsi-for-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/joel/fsi into char-misc-next

Joel writes:

FSI changes for 5.10

 - Misc code cleanups. Thanks to Colin, Xu and Rikard

 - Features for the ASPEED FSI master
  * Detect connection type and routing for Tacoma
  * Run at full speed (200MHz) by default
  * Set bus speed with a parameter
  * CFAM reset GPIO
  * 23 bit addressing

 - Core features
  * Disable unused links
  * Set LBUS ownership

* tag 'fsi-for-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/joel/fsi:
  fsi: aspeed: Support CFAM reset GPIO
  fsi: aspeed: Add module param for bus divisor
  fsi: aspeed: Run the bus at maximum speed
  fsi: aspeed: Support cabled FSI
  dt-bindings: fsi: Document gpios
  fsi: scom: Constify scom_ids
  fsi: sbefifo: Constify sbefifo_ids
  fsi: master: Constify hub_master_ids
  fsi: master: Remove link enable read-back
  fsi: core: Set slave local bus ownership during init
  fsi: core: Disable link when slave init fails
  fsi: master: Add boolean parameter to link_enable function
  fsi: fsi-occ: fix return value check in occ_probe()
  fsi: aspeed: Enable 23-bit addressing
  fsi: master-ast-cf: fix spelling mistake "firwmare" -> "firmware"
This commit is contained in:
Greg Kroah-Hartman 2020-09-11 14:22:32 +02:00
commit f7dbcd1770
11 changed files with 188 additions and 33 deletions

View File

@ -36,3 +36,11 @@ Contact: linux-fsi@lists.ozlabs.org
Description:
Provides a means of reading/writing a 32 bit value from/to a
specified FSI bus address.
What: /sys/bus/platform/devices/../cfam_reset
Date: Sept 2020
KernelVersion: 5.10
Contact: linux-fsi@lists.ozlabs.org
Description:
Provides a means of resetting the cfam that is attached to the
FSI device.

View File

@ -12,6 +12,13 @@ Required properties:
- pinctrl-0: phandle to pinctrl node
- pinctrl-names: pinctrl state
Optional properties:
- cfam-reset-gpios: GPIO for CFAM reset
- fsi-routing-gpios: GPIO for setting the FSI mux (internal or cabled)
- fsi-mux-gpios: GPIO for detecting the desired FSI mux state
Examples:
fsi-master {
@ -21,4 +28,9 @@ Examples:
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_fsi1_default>;
clocks = <&syscon ASPEED_CLK_GATE_FSICLK>;
fsi-routing-gpios = <&gpio0 ASPEED_GPIO(Q, 7) GPIO_ACTIVE_HIGH>;
fsi-mux-gpios = <&gpio0 ASPEED_GPIO(B, 0) GPIO_ACTIVE_HIGH>;
cfam-reset-gpios = <&gpio0 ASPEED_GPIO(Q, 0) GPIO_ACTIVE_LOW>;
};

View File

@ -50,6 +50,7 @@ static const int engine_page_size = 0x400;
#define FSI_SMODE 0x0 /* R/W: Mode register */
#define FSI_SISC 0x8 /* R/W: Interrupt condition */
#define FSI_SSTAT 0x14 /* R : Slave status */
#define FSI_SLBUS 0x30 /* W : LBUS Ownership */
#define FSI_LLMODE 0x100 /* R/W: Link layer mode register */
/*
@ -66,6 +67,11 @@ static const int engine_page_size = 0x400;
#define FSI_SMODE_LBCRR_SHIFT 8 /* Clk ratio shift */
#define FSI_SMODE_LBCRR_MASK 0xf /* Clk ratio mask */
/*
* SLBUS fields
*/
#define FSI_SLBUS_FORCE 0x80000000 /* Force LBUS ownership */
/*
* LLMODE fields
*/
@ -981,7 +987,7 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
uint32_t cfam_id;
struct fsi_slave *slave;
uint8_t crc;
__be32 data, llmode;
__be32 data, llmode, slbus;
int rc;
/* Currently, we only support single slaves on a link, and use the
@ -1052,6 +1058,14 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
}
slbus = cpu_to_be32(FSI_SLBUS_FORCE);
rc = fsi_master_write(master, link, id, FSI_SLAVE_BASE + FSI_SLBUS,
&slbus, sizeof(slbus));
if (rc)
dev_warn(&master->dev,
"can't set slbus on slave:%02x:%02x %d\n", link, id,
rc);
rc = fsi_slave_set_smode(slave);
if (rc) {
dev_warn(&master->dev,
@ -1154,10 +1168,18 @@ static int fsi_master_write(struct fsi_master *master, int link,
return rc;
}
static int fsi_master_link_disable(struct fsi_master *master, int link)
{
if (master->link_enable)
return master->link_enable(master, link, false);
return 0;
}
static int fsi_master_link_enable(struct fsi_master *master, int link)
{
if (master->link_enable)
return master->link_enable(master, link);
return master->link_enable(master, link, true);
return 0;
}
@ -1192,12 +1214,15 @@ static int fsi_master_scan(struct fsi_master *master)
}
rc = fsi_master_break(master, link);
if (rc) {
fsi_master_link_disable(master, link);
dev_dbg(&master->dev,
"break to link %d failed: %d\n", link, rc);
continue;
}
fsi_slave_init(master, link, 0);
rc = fsi_slave_init(master, link, 0);
if (rc)
fsi_master_link_disable(master, link);
}
return 0;

View File

@ -13,6 +13,7 @@
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/iopoll.h>
#include <linux/gpio/consumer.h>
#include "fsi-master.h"
@ -21,6 +22,7 @@ struct fsi_master_aspeed {
struct device *dev;
void __iomem *base;
struct clk *clk;
struct gpio_desc *cfam_reset_gpio;
};
#define to_fsi_master_aspeed(m) \
@ -82,7 +84,12 @@ static const u32 fsi_base = 0xa0000000;
#define FSI_LINK_ENABLE_SETUP_TIME 10 /* in mS */
#define DEFAULT_DIVISOR 14
/* Run the bus at maximum speed by default */
#define FSI_DIVISOR_DEFAULT 1
#define FSI_DIVISOR_CABLED 2
static u16 aspeed_fsi_divisor = FSI_DIVISOR_DEFAULT;
module_param_named(bus_div,aspeed_fsi_divisor, ushort, 0);
#define OPB_POLL_TIMEOUT 10000
static int __opb_write(struct fsi_master_aspeed *aspeed, u32 addr,
@ -241,9 +248,10 @@ static int aspeed_master_read(struct fsi_master *master, int link,
struct fsi_master_aspeed *aspeed = to_fsi_master_aspeed(master);
int ret;
if (id != 0)
if (id > 0x3)
return -EINVAL;
addr |= id << 21;
addr += link * FSI_HUB_LINK_SIZE;
switch (size) {
@ -273,9 +281,10 @@ static int aspeed_master_write(struct fsi_master *master, int link,
struct fsi_master_aspeed *aspeed = to_fsi_master_aspeed(master);
int ret;
if (id != 0)
if (id > 0x3)
return -EINVAL;
addr |= id << 21;
addr += link * FSI_HUB_LINK_SIZE;
switch (size) {
@ -299,32 +308,28 @@ static int aspeed_master_write(struct fsi_master *master, int link,
return 0;
}
static int aspeed_master_link_enable(struct fsi_master *master, int link)
static int aspeed_master_link_enable(struct fsi_master *master, int link,
bool enable)
{
struct fsi_master_aspeed *aspeed = to_fsi_master_aspeed(master);
int idx, bit, ret;
__be32 reg, result;
__be32 reg;
idx = link / 32;
bit = link % 32;
reg = cpu_to_be32(0x80000000 >> bit);
if (!enable)
return opb_writel(aspeed, ctrl_base + FSI_MCENP0 + (4 * idx),
reg);
ret = opb_writel(aspeed, ctrl_base + FSI_MSENP0 + (4 * idx), reg);
if (ret)
return ret;
mdelay(FSI_LINK_ENABLE_SETUP_TIME);
ret = opb_readl(aspeed, ctrl_base + FSI_MENP0 + (4 * idx), &result);
if (ret)
return ret;
if (result != reg) {
dev_err(aspeed->dev, "%s failed: %08x\n", __func__, result);
return -EIO;
}
return 0;
}
@ -386,9 +391,11 @@ static int aspeed_master_init(struct fsi_master_aspeed *aspeed)
opb_writel(aspeed, ctrl_base + FSI_MECTRL, reg);
reg = cpu_to_be32(FSI_MMODE_ECRC | FSI_MMODE_EPC | FSI_MMODE_RELA
| fsi_mmode_crs0(DEFAULT_DIVISOR)
| fsi_mmode_crs1(DEFAULT_DIVISOR)
| fsi_mmode_crs0(aspeed_fsi_divisor)
| fsi_mmode_crs1(aspeed_fsi_divisor)
| FSI_MMODE_P8_TO_LSB);
dev_info(aspeed->dev, "mmode set to %08x (divisor %d)\n",
be32_to_cpu(reg), aspeed_fsi_divisor);
opb_writel(aspeed, ctrl_base + FSI_MMODE, reg);
reg = cpu_to_be32(0xffff0000);
@ -419,6 +426,90 @@ static int aspeed_master_init(struct fsi_master_aspeed *aspeed)
return 0;
}
static ssize_t cfam_reset_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct fsi_master_aspeed *aspeed = dev_get_drvdata(dev);
gpiod_set_value(aspeed->cfam_reset_gpio, 1);
usleep_range(900, 1000);
gpiod_set_value(aspeed->cfam_reset_gpio, 0);
return count;
}
static DEVICE_ATTR(cfam_reset, 0200, NULL, cfam_reset_store);
static int setup_cfam_reset(struct fsi_master_aspeed *aspeed)
{
struct device *dev = aspeed->dev;
struct gpio_desc *gpio;
int rc;
gpio = devm_gpiod_get_optional(dev, "cfam-reset", GPIOD_OUT_LOW);
if (IS_ERR(gpio))
return PTR_ERR(gpio);
if (!gpio)
return 0;
aspeed->cfam_reset_gpio = gpio;
rc = device_create_file(dev, &dev_attr_cfam_reset);
if (rc) {
devm_gpiod_put(dev, gpio);
return rc;
}
return 0;
}
static int tacoma_cabled_fsi_fixup(struct device *dev)
{
struct gpio_desc *routing_gpio, *mux_gpio;
int gpio;
/*
* The routing GPIO is a jumper indicating we should mux for the
* externally connected FSI cable.
*/
routing_gpio = devm_gpiod_get_optional(dev, "fsi-routing",
GPIOD_IN | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
if (IS_ERR(routing_gpio))
return PTR_ERR(routing_gpio);
if (!routing_gpio)
return 0;
mux_gpio = devm_gpiod_get_optional(dev, "fsi-mux", GPIOD_ASIS);
if (IS_ERR(mux_gpio))
return PTR_ERR(mux_gpio);
if (!mux_gpio)
return 0;
gpio = gpiod_get_value(routing_gpio);
if (gpio < 0)
return gpio;
/* If the routing GPIO is high we should set the mux to low. */
if (gpio) {
/*
* Cable signal integrity means we should run the bus
* slightly slower. Do not override if a kernel param
* has already overridden.
*/
if (aspeed_fsi_divisor == FSI_DIVISOR_DEFAULT)
aspeed_fsi_divisor = FSI_DIVISOR_CABLED;
gpiod_direction_output(mux_gpio, 0);
dev_info(dev, "FSI configured for external cable\n");
} else {
gpiod_direction_output(mux_gpio, 1);
}
devm_gpiod_put(dev, routing_gpio);
return 0;
}
static int fsi_master_aspeed_probe(struct platform_device *pdev)
{
struct fsi_master_aspeed *aspeed;
@ -426,6 +517,12 @@ static int fsi_master_aspeed_probe(struct platform_device *pdev)
int rc, links, reg;
__be32 raw;
rc = tacoma_cabled_fsi_fixup(&pdev->dev);
if (rc) {
dev_err(&pdev->dev, "Tacoma FSI cable fixup failed\n");
return rc;
}
aspeed = devm_kzalloc(&pdev->dev, sizeof(*aspeed), GFP_KERNEL);
if (!aspeed)
return -ENOMEM;
@ -448,6 +545,11 @@ static int fsi_master_aspeed_probe(struct platform_device *pdev)
return rc;
}
rc = setup_cfam_reset(aspeed);
if (rc) {
dev_err(&pdev->dev, "CFAM reset GPIO setup failed\n");
}
writel(0x1, aspeed->base + OPB_CLK_SYNC);
writel(OPB1_XFER_ACK_EN | OPB0_XFER_ACK_EN,
aspeed->base + OPB_IRQ_MASK);

View File

@ -838,7 +838,7 @@ static int load_copro_firmware(struct fsi_master_acf *master)
rc = request_firmware(&fw, FW_FILE_NAME, master->dev);
if (rc) {
dev_err(
master->dev, "Error %d to load firwmare '%s' !\n",
master->dev, "Error %d to load firmware '%s' !\n",
rc, FW_FILE_NAME);
return rc;
}
@ -1039,7 +1039,8 @@ static void fsi_master_acf_setup_external(struct fsi_master_acf *master)
gpiod_direction_input(master->gpio_data);
}
static int fsi_master_acf_link_enable(struct fsi_master *_master, int link)
static int fsi_master_acf_link_enable(struct fsi_master *_master, int link,
bool enable)
{
struct fsi_master_acf *master = to_fsi_master_acf(_master);
int rc = -EBUSY;
@ -1049,7 +1050,7 @@ static int fsi_master_acf_link_enable(struct fsi_master *_master, int link)
mutex_lock(&master->lock);
if (!master->external_mode) {
gpiod_set_value(master->gpio_enable, 1);
gpiod_set_value(master->gpio_enable, enable ? 1 : 0);
rc = 0;
}
mutex_unlock(&master->lock);

View File

@ -678,7 +678,8 @@ static void fsi_master_gpio_init_external(struct fsi_master_gpio *master)
gpiod_direction_input(master->gpio_data);
}
static int fsi_master_gpio_link_enable(struct fsi_master *_master, int link)
static int fsi_master_gpio_link_enable(struct fsi_master *_master, int link,
bool enable)
{
struct fsi_master_gpio *master = to_fsi_master_gpio(_master);
int rc = -EBUSY;
@ -688,7 +689,7 @@ static int fsi_master_gpio_link_enable(struct fsi_master *_master, int link)
mutex_lock(&master->cmd_lock);
if (!master->external_mode) {
gpiod_set_value(master->gpio_enable, 1);
gpiod_set_value(master->gpio_enable, enable ? 1 : 0);
rc = 0;
}
mutex_unlock(&master->cmd_lock);

View File

@ -77,7 +77,8 @@ static int hub_master_break(struct fsi_master *master, int link)
return hub_master_write(master, link, 0, addr, &cmd, sizeof(cmd));
}
static int hub_master_link_enable(struct fsi_master *master, int link)
static int hub_master_link_enable(struct fsi_master *master, int link,
bool enable)
{
struct fsi_master_hub *hub = to_fsi_master_hub(master);
int idx, bit;
@ -89,13 +90,17 @@ static int hub_master_link_enable(struct fsi_master *master, int link)
reg = cpu_to_be32(0x80000000 >> bit);
if (!enable)
return fsi_device_write(hub->upstream, FSI_MCENP0 + (4 * idx),
&reg, 4);
rc = fsi_device_write(hub->upstream, FSI_MSENP0 + (4 * idx), &reg, 4);
if (rc)
return rc;
mdelay(FSI_LINK_ENABLE_SETUP_TIME);
fsi_device_read(hub->upstream, FSI_MENP0 + (4 * idx), &reg, 4);
return rc;
return 0;
}
static void hub_master_release(struct device *dev)
@ -271,7 +276,7 @@ static int hub_master_remove(struct device *dev)
return 0;
}
static struct fsi_device_id hub_master_ids[] = {
static const struct fsi_device_id hub_master_ids[] = {
{
.engine_type = FSI_ENGID_HUB_MASTER,
.version = FSI_VERSION_ANY,

View File

@ -130,7 +130,8 @@ struct fsi_master {
uint32_t addr, const void *val, size_t size);
int (*term)(struct fsi_master *, int link, uint8_t id);
int (*send_break)(struct fsi_master *, int link);
int (*link_enable)(struct fsi_master *, int link);
int (*link_enable)(struct fsi_master *, int link,
bool enable);
int (*link_config)(struct fsi_master *, int link,
u8 t_send_delay, u8 t_echo_delay);
};

View File

@ -555,7 +555,7 @@ static int occ_probe(struct platform_device *pdev)
hwmon_dev_info.id = occ->idx;
hwmon_dev = platform_device_register_full(&hwmon_dev_info);
if (!hwmon_dev)
if (IS_ERR(hwmon_dev))
dev_warn(dev, "failed to create hwmon device\n");
return 0;

View File

@ -1028,7 +1028,7 @@ static int sbefifo_remove(struct device *dev)
return 0;
}
static struct fsi_device_id sbefifo_ids[] = {
static const struct fsi_device_id sbefifo_ids[] = {
{
.engine_type = FSI_ENGID_SBE,
.version = FSI_VERSION_ANY,

View File

@ -627,7 +627,7 @@ static int scom_remove(struct device *dev)
return 0;
}
static struct fsi_device_id scom_ids[] = {
static const struct fsi_device_id scom_ids[] = {
{
.engine_type = FSI_ENGID_SCOM,
.version = FSI_VERSION_ANY,