Re: [PATCH 0/4] occ: fsi and hwmon: Fixes for polling un-initialized OCC

2021-04-05 Thread Eddie James
On Tue, 2021-02-09 at 11:12 -0600, Eddie James wrote:
> In the event that the OCC is not initialized when the driver sends a
> poll
> command, the driver may receive an invalid response. This isn't an
> error
> condition unless there is no valid response before the timeout
> expires. So
> change the starting sequence number and check for the un-initialized
> OCC
> state before returning the response in order to detect this condition
> and
> continue waiting if necessary.

Hi Joel,

Do you have any comments on the FSI side of this series?

Thanks,
Eddie

> 
> Eddie James (4):
>   fsi: occ: Don't accept response from un-initialized OCC
>   fsi: occ: Log error for checksum failure
>   hwmon: (occ) Start sequence number at one
>   hwmon: (occ) Print response status in first poll error message
> 
>  drivers/fsi/fsi-occ.c  | 11 ---
>  drivers/hwmon/occ/common.c |  7 +--
>  2 files changed, 13 insertions(+), 5 deletions(-)
> 



[PATCH] net/ncsi: Avoid channel_monitor hrtimer deadlock

2021-03-29 Thread Eddie James
From: Milton Miller 

Calling ncsi_stop_channel_monitor from channel_monitor is a guaranteed
deadlock on SMP because stop calls del_timer_sync on the timer that
inoked channel_monitor as its timer function.

Recognise the inherent race of marking the monitor disabled before
deleting the timer by just returning if enable was cleared.  After
a timeout (the default case -- reset to START when response received)
just mark the monitor.enabled false.

If the channel has an entrie on the channel_queue list, or if the
state is not ACTIVE or INACTIVE, then warn and mark the timer stopped
and don't restart, as the locking is broken somehow.

Fixes: 0795fb2021f0 ("net/ncsi: Stop monitor if channel times out or is 
inactive")
Signed-off-by: Milton Miller 
Signed-off-by: Eddie James 
---
 net/ncsi/ncsi-manage.c | 20 +---
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index a9cb355324d1..8da707b8 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -105,13 +105,20 @@ static void ncsi_channel_monitor(struct timer_list *t)
monitor_state = nc->monitor.state;
spin_unlock_irqrestore(>lock, flags);
 
-   if (!enabled || chained) {
-   ncsi_stop_channel_monitor(nc);
-   return;
-   }
+   if (!enabled)
+   return; /* expected race disabling timer */
+   if (WARN_ON_ONCE(chained))
+   goto bad_state;
+
if (state != NCSI_CHANNEL_INACTIVE &&
state != NCSI_CHANNEL_ACTIVE) {
-   ncsi_stop_channel_monitor(nc);
+bad_state:
+   netdev_warn(ndp->ndev.dev,
+   "Bad NCSI monitor state channel %d 0x%x %s queue\n",
+   nc->id, state, chained ? "on" : "off");
+   spin_lock_irqsave(>lock, flags);
+   nc->monitor.enabled = false;
+   spin_unlock_irqrestore(>lock, flags);
return;
}
 
@@ -136,10 +143,9 @@ static void ncsi_channel_monitor(struct timer_list *t)
ncsi_report_link(ndp, true);
ndp->flags |= NCSI_DEV_RESHUFFLE;
 
-   ncsi_stop_channel_monitor(nc);
-
ncm = >modes[NCSI_MODE_LINK];
spin_lock_irqsave(>lock, flags);
+   nc->monitor.enabled = false;
nc->state = NCSI_CHANNEL_INVISIBLE;
ncm->data[2] &= ~0x1;
spin_unlock_irqrestore(>lock, flags);
-- 
2.27.0



[PATCH] fsi: scom: Reset the FSI2PIB engine for any error

2021-03-29 Thread Eddie James
The error bits in the FSI2PIB status are only cleared by a reset. So
the driver needs to perform a reset after seeing any of the FSI2PIB
errors, otherwise subsequent operations will also look like failures.

Fixes: 6b293258cded ("fsi: scom: Major overhaul")
Signed-off-by: Eddie James 
---
 drivers/fsi/fsi-scom.c | 16 +---
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/fsi/fsi-scom.c b/drivers/fsi/fsi-scom.c
index b45bfab7b7f5..75d1389e2626 100644
--- a/drivers/fsi/fsi-scom.c
+++ b/drivers/fsi/fsi-scom.c
@@ -38,9 +38,10 @@
 #define SCOM_STATUS_PIB_RESP_MASK  0x7000
 #define SCOM_STATUS_PIB_RESP_SHIFT 12
 
-#define SCOM_STATUS_ANY_ERR(SCOM_STATUS_PROTECTION | \
-SCOM_STATUS_PARITY | \
-SCOM_STATUS_PIB_ABORT | \
+#define SCOM_STATUS_FSI2PIB_ERROR  (SCOM_STATUS_PROTECTION |   \
+SCOM_STATUS_PARITY |   \
+SCOM_STATUS_PIB_ABORT)
+#define SCOM_STATUS_ANY_ERR(SCOM_STATUS_FSI2PIB_ERROR |\
 SCOM_STATUS_PIB_RESP_MASK)
 /* SCOM address encodings */
 #define XSCOM_ADDR_IND_FLAGBIT_ULL(63)
@@ -240,13 +241,14 @@ static int handle_fsi2pib_status(struct scom_device 
*scom, uint32_t status)
 {
uint32_t dummy = -1;
 
-   if (status & SCOM_STATUS_PROTECTION)
-   return -EPERM;
-   if (status & SCOM_STATUS_PARITY) {
+   if (status & SCOM_STATUS_FSI2PIB_ERROR)
fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, ,
 sizeof(uint32_t));
+
+   if (status & SCOM_STATUS_PROTECTION)
+   return -EPERM;
+   if (status & SCOM_STATUS_PARITY)
return -EIO;
-   }
/* Return -EBUSY on PIB abort to force a retry */
if (status & SCOM_STATUS_PIB_ABORT)
return -EBUSY;
-- 
2.27.0



Re: [PATCH] spi: fsi: Remove multiple sequenced ops for restricted chips

2021-03-25 Thread Eddie James
On Thu, 2021-03-25 at 13:50 +, Mark Brown wrote:
> On Wed, Mar 24, 2021 at 05:05:16PM -0500, Eddie James wrote:
> 
> > Updated restricted chips have trouble processing multiple sequenced
> > operations. So remove the capability to sequence multiple
> > operations and
> > reduce the maximum transfer size to 8 bytes.
> 
> That's a very small limit, it would be nice to be able to identify
> devices that can use the larger limit so they don't suffer
> needlessly.

Yes, this is only for the "restricted" controllers which are marked by
a different compatible string. I guess the commit message isn't
perfectly clear.

Thanks,
Eddie




[PATCH] spi: fsi: Remove multiple sequenced ops for restricted chips

2021-03-24 Thread Eddie James
Updated restricted chips have trouble processing multiple sequenced
operations. So remove the capability to sequence multiple operations and
reduce the maximum transfer size to 8 bytes.

Signed-off-by: Eddie James 
---
 drivers/spi/spi-fsi.c | 27 +++
 1 file changed, 7 insertions(+), 20 deletions(-)

diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c
index 3920cd3286d8..de359718e816 100644
--- a/drivers/spi/spi-fsi.c
+++ b/drivers/spi/spi-fsi.c
@@ -26,7 +26,7 @@
 #define SPI_FSI_BASE   0x7
 #define SPI_FSI_INIT_TIMEOUT_MS1000
 #define SPI_FSI_MAX_XFR_SIZE   2048
-#define SPI_FSI_MAX_XFR_SIZE_RESTRICTED32
+#define SPI_FSI_MAX_XFR_SIZE_RESTRICTED8
 
 #define SPI_FSI_ERROR  0x0
 #define SPI_FSI_COUNTER_CFG0x1
@@ -265,14 +265,12 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
 struct fsi_spi_sequence *seq,
 struct spi_transfer *transfer)
 {
-   bool docfg = false;
int loops;
int idx;
int rc;
u8 val = 0;
u8 len = min(transfer->len, 8U);
u8 rem = transfer->len % len;
-   u64 cfg = 0ULL;
 
loops = transfer->len / len;
 
@@ -292,28 +290,17 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
return -EINVAL;
}
 
-   if (ctx->restricted) {
-   const int eidx = rem ? 5 : 6;
-
-   while (loops > 1 && idx <= eidx) {
-   idx = fsi_spi_sequence_add(seq, val);
-   loops--;
-   docfg = true;
-   }
-
-   if (loops > 1) {
-   dev_warn(ctx->dev, "No sequencer slots; aborting.\n");
-   return -EINVAL;
-   }
+   if (ctx->restricted && loops > 1) {
+   dev_warn(ctx->dev,
+"Transfer too large; no branches permitted.\n");
+   return -EINVAL;
}
 
if (loops > 1) {
+   u64 cfg = SPI_FSI_COUNTER_CFG_LOOPS(loops - 1);
+
fsi_spi_sequence_add(seq, SPI_FSI_SEQUENCE_BRANCH(idx));
-   docfg = true;
-   }
 
-   if (docfg) {
-   cfg = SPI_FSI_COUNTER_CFG_LOOPS(loops - 1);
if (transfer->rx_buf)
cfg |= SPI_FSI_COUNTER_CFG_N2_RX |
SPI_FSI_COUNTER_CFG_N2_TX |
-- 
2.27.0



[PATCH] fsi: Aspeed: Reduce poll timeout

2021-02-11 Thread Eddie James
The lengthy timeout previously used sometimes resulted in
scheduling problems, detailed below. Therefore reduce the timeout
to 500us. This timeout selection is supported by the benchmarks
collected below with various clock dividers. This is purely the time
spent polling (reported by ktime_get()).

div  1: max:150us avg:  2us
div  2: max:155us avg:  3us
div  4: max:149us avg:  7us
div  8: max:153us avg: 13us
div 16: max:197us avg: 21us
div 32: max:181us avg: 50us
div 64: max:262us avg:100us

Jan 22 01:27:21 rain27bmc kernel: rcu: INFO: rcu_sched self-detected stall on 
CPU
Jan 22 01:27:21 rain27bmc kernel: rcu: 0-: (2099 ticks this GP) 
idle=0ca/1/0x4002 softirq=349573/349573 fqs=1048
Jan 22 01:27:21 rain27bmc kernel: (t=2100 jiffies g=841149 q=7163)
Jan 22 01:27:21 rain27bmc kernel: NMI backtrace for cpu 0
Jan 22 01:27:21 rain27bmc kernel: CPU: 0 PID: 5959 Comm: ibm-read-vpd Not 
tainted 5.8.17-a9b4ea8 #1
Jan 22 01:27:21 rain27bmc kernel: Hardware name: Generic DT based system
Jan 22 01:27:21 rain27bmc kernel: Backtrace:
Jan 22 01:27:25 rain27bmc kernel: [<8010d92c>] (dump_backtrace) from 
[<8010db80>] (show_stack+0x20/0x24)
...
Jan 22 01:27:25 rain27bmc kernel: [<8010130c>] (gic_handle_irq) from 
[<80100b0c>] (__irq_svc+0x6c/0x90)
Jan 22 01:27:25 rain27bmc kernel: Exception stack(0xb79159b0 to 0xb79159f8)
Jan 22 01:27:25 rain27bmc kernel: 59a0: 
9e88e5d5 0559 0559 0018
Jan 22 01:27:25 rain27bmc kernel: 59c0:  9f217c55 0003 0559 
a0201c00 bfa4d048 bfa4d000 b7915a44
Jan 22 01:27:25 rain27bmc kernel: 59e0: 40e88f8a b7915a00 3254e553 80734924 
80030113 
Jan 22 01:27:25 rain27bmc kernel:  r9:b7914000 r8:a0201c00 r7:b79159e4 
r6: r5:80030113 r4:80734924
Jan 22 01:27:25 rain27bmc kernel: [<807348b4>] (__opb_read) from [<80734d98>] 
(aspeed_master_read+0xbc/0xcc)
Jan 22 01:27:25 rain27bmc kernel:  r10:0004 r9:0002 r8:80734cdc 
r7:bd33fa40 r6:0004 r5:bd33f840
Jan 22 01:27:25 rain27bmc kernel:  r4:00201c00
Jan 22 01:27:25 rain27bmc kernel: [<80734cdc>] (aspeed_master_read) from 
[<807320f0>] (fsi_master_read+0x6c/0x1bc)
...

Signed-off-by: Eddie James 
---
 drivers/fsi/fsi-master-aspeed.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/fsi/fsi-master-aspeed.c b/drivers/fsi/fsi-master-aspeed.c
index 90dbe58ca1ed..03c61e50b299 100644
--- a/drivers/fsi/fsi-master-aspeed.c
+++ b/drivers/fsi/fsi-master-aspeed.c
@@ -92,7 +92,7 @@ static const u32 fsi_base = 0xa000;
 static u16 aspeed_fsi_divisor = FSI_DIVISOR_DEFAULT;
 module_param_named(bus_div,aspeed_fsi_divisor, ushort, 0);
 
-#define OPB_POLL_TIMEOUT   1
+#define OPB_POLL_TIMEOUT   500
 
 static int __opb_write(struct fsi_master_aspeed *aspeed, u32 addr,
   u32 val, u32 transfer_size)
-- 
2.27.0



[PATCH 4/4] hwmon: (occ) Print response status in first poll error message

2021-02-09 Thread Eddie James
In order to better debug problems starting up the driver, print
the response status from the OCC in the error logged when the first
poll command fails.

Signed-off-by: Eddie James 
---
 drivers/hwmon/occ/common.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c
index ee0c5d12dfdf..f71d62b57468 100644
--- a/drivers/hwmon/occ/common.c
+++ b/drivers/hwmon/occ/common.c
@@ -1161,8 +1161,9 @@ int occ_setup(struct occ *occ, const char *name)
dev_info(occ->bus_dev, "host is not ready\n");
return rc;
} else if (rc < 0) {
-   dev_err(occ->bus_dev, "failed to get OCC poll response: %d\n",
-   rc);
+   dev_err(occ->bus_dev,
+   "failed to get OCC poll response=%02x: %d\n",
+   occ->resp.return_status, rc);
return rc;
}
 
-- 
2.27.0



[PATCH 3/4] hwmon: (occ) Start sequence number at one

2021-02-09 Thread Eddie James
Initialize the sequence number at one, rather than zero, in order
to prevent false matches with the zero-initialized OCC SRAM
buffer before the OCC is fully initialized.

Signed-off-by: Eddie James 
---
 drivers/hwmon/occ/common.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c
index 7a5e539b567b..ee0c5d12dfdf 100644
--- a/drivers/hwmon/occ/common.c
+++ b/drivers/hwmon/occ/common.c
@@ -1150,6 +1150,8 @@ int occ_setup(struct occ *occ, const char *name)
 {
int rc;
 
+   /* start with 1 to avoid false match with zero-initialized SRAM buffer 
*/
+   occ->seq_no = 1;
mutex_init(>lock);
occ->groups[0] = >group;
 
-- 
2.27.0



[PATCH 2/4] fsi: occ: Log error for checksum failure

2021-02-09 Thread Eddie James
Log an error if the response checksum doesn't match the
calculated checksum.

Signed-off-by: Eddie James 
---
 drivers/fsi/fsi-occ.c | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/fsi/fsi-occ.c b/drivers/fsi/fsi-occ.c
index cb05b6dacc9d..524460995465 100644
--- a/drivers/fsi/fsi-occ.c
+++ b/drivers/fsi/fsi-occ.c
@@ -223,7 +223,8 @@ static const struct file_operations occ_fops = {
.release = occ_release,
 };
 
-static int occ_verify_checksum(struct occ_response *resp, u16 data_length)
+static int occ_verify_checksum(struct occ *occ, struct occ_response *resp,
+  u16 data_length)
 {
/* Fetch the two bytes after the data for the checksum. */
u16 checksum_resp = get_unaligned_be16(>data[data_length]);
@@ -238,8 +239,11 @@ static int occ_verify_checksum(struct occ_response *resp, 
u16 data_length)
for (i = 0; i < data_length; ++i)
checksum += resp->data[i];
 
-   if (checksum != checksum_resp)
+   if (checksum != checksum_resp) {
+   dev_err(occ->dev, "Bad checksum: %04x!=%04x\n", checksum,
+   checksum_resp);
return -EBADMSG;
+   }
 
return 0;
 }
@@ -533,7 +537,7 @@ int fsi_occ_submit(struct device *dev, const void *request, 
size_t req_len,
}
 
*resp_len = resp_data_length + 7;
-   rc = occ_verify_checksum(resp, resp_data_length);
+   rc = occ_verify_checksum(occ, resp, resp_data_length);
 
  done:
mutex_unlock(>occ_lock);
-- 
2.27.0



[PATCH 0/4] occ: fsi and hwmon: Fixes for polling un-initialized OCC

2021-02-09 Thread Eddie James
In the event that the OCC is not initialized when the driver sends a poll
command, the driver may receive an invalid response. This isn't an error
condition unless there is no valid response before the timeout expires. So
change the starting sequence number and check for the un-initialized OCC
state before returning the response in order to detect this condition and
continue waiting if necessary.

Eddie James (4):
  fsi: occ: Don't accept response from un-initialized OCC
  fsi: occ: Log error for checksum failure
  hwmon: (occ) Start sequence number at one
  hwmon: (occ) Print response status in first poll error message

 drivers/fsi/fsi-occ.c  | 11 ---
 drivers/hwmon/occ/common.c |  7 +--
 2 files changed, 13 insertions(+), 5 deletions(-)

-- 
2.27.0



[PATCH 1/4] fsi: occ: Don't accept response from un-initialized OCC

2021-02-09 Thread Eddie James
If the OCC is not initialized and responds as such, the driver
should continue waiting for a valid response until the timeout
expires.

Signed-off-by: Eddie James 
---
 drivers/fsi/fsi-occ.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/fsi/fsi-occ.c b/drivers/fsi/fsi-occ.c
index 10ca2e290655..cb05b6dacc9d 100644
--- a/drivers/fsi/fsi-occ.c
+++ b/drivers/fsi/fsi-occ.c
@@ -495,6 +495,7 @@ int fsi_occ_submit(struct device *dev, const void *request, 
size_t req_len,
goto done;
 
if (resp->return_status == OCC_RESP_CMD_IN_PRG ||
+   resp->return_status == OCC_RESP_CRIT_INIT ||
resp->seq_no != seq_no) {
rc = -ETIMEDOUT;
 
-- 
2.27.0



[PATCH v2 1/2] hwmon: (pmbus) Add a PMBUS_NO_CAPABILITY platform data flag

2020-12-22 Thread Eddie James
Some PMBus chips don't respond with valid data when reading the
CAPABILITY register. Add a flag that device drivers can set so
that the PMBus core driver doesn't use CAPABILITY to determine it's
behavior.

Signed-off-by: Eddie James 
---
 drivers/hwmon/pmbus/pmbus_core.c | 8 +---
 include/linux/pmbus.h| 9 +
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 192442b3b7a2..906c9fec9cce 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -2204,9 +2204,11 @@ static int pmbus_init_common(struct i2c_client *client, 
struct pmbus_data *data,
}
 
/* Enable PEC if the controller supports it */
-   ret = i2c_smbus_read_byte_data(client, PMBUS_CAPABILITY);
-   if (ret >= 0 && (ret & PB_CAPABILITY_ERROR_CHECK))
-   client->flags |= I2C_CLIENT_PEC;
+   if (!(data->flags & PMBUS_NO_CAPABILITY)) {
+   ret = i2c_smbus_read_byte_data(client, PMBUS_CAPABILITY);
+   if (ret >= 0 && (ret & PB_CAPABILITY_ERROR_CHECK))
+   client->flags |= I2C_CLIENT_PEC;
+   }
 
/*
 * Check if the chip is write protected. If it is, we can not clear
diff --git a/include/linux/pmbus.h b/include/linux/pmbus.h
index 1ea5bae708a1..12cbbf305969 100644
--- a/include/linux/pmbus.h
+++ b/include/linux/pmbus.h
@@ -34,6 +34,15 @@
  */
 #define PMBUS_WRITE_PROTECTED  BIT(1)
 
+/*
+ * PMBUS_NO_CAPABILITY
+ *
+ * Some PMBus chips don't respond with valid data when reading the CAPABILITY
+ * register. For such chips, this flag should be set so that the PMBus core
+ * driver doesn't use CAPABILITY to determine it's behavior.
+ */
+#define PMBUS_NO_CAPABILITYBIT(2)
+
 struct pmbus_platform_data {
u32 flags;  /* Device specific flags */
 
-- 
2.27.0



[PATCH v2 2/2] hwmon: (pmbus/ibm-cffps) Set the PMBUS_NO_CAPABILITY flag

2020-12-22 Thread Eddie James
Several power supplies supported by the IBM CFFPS driver don't
report valid data in the CAPABILITY register. This results in PEC
being enabled when it's not supported by the device, and since
the automatic version detection might fail, disable use of the
CAPABILITY register across the board for this driver.

Signed-off-by: Eddie James 
---
 drivers/hwmon/pmbus/ibm-cffps.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hwmon/pmbus/ibm-cffps.c b/drivers/hwmon/pmbus/ibm-cffps.c
index d6223871..ffde5aaa5036 100644
--- a/drivers/hwmon/pmbus/ibm-cffps.c
+++ b/drivers/hwmon/pmbus/ibm-cffps.c
@@ -472,7 +472,7 @@ static struct pmbus_driver_info ibm_cffps_info[] = {
 };
 
 static struct pmbus_platform_data ibm_cffps_pdata = {
-   .flags = PMBUS_SKIP_STATUS_CHECK,
+   .flags = PMBUS_SKIP_STATUS_CHECK | PMBUS_NO_CAPABILITY,
 };
 
 static int ibm_cffps_probe(struct i2c_client *client)
-- 
2.27.0



[PATCH v2 0/2] hwmon: (pmbus) Add the PMBUS_NO_CAPABILITY flag

2020-12-22 Thread Eddie James
Some PMBus chips, like some power supplies supported by the cffps driver,
don't respond with valid data when reading the CAPABILITY register. Add a
platform data flag that device drivers can set to tell the PMBus core
driver that it shouldn't use the CAPABILITY register. The second patch
sets this flag for the cffps driver.

Changes since v1:
 - Rename the flag to PMBUS_NO_CAPABILITY and adjust the associated
   comment accordingly.

Eddie James (2):
  hwmon: (pmbus) Add a PMBUS_NO_CAPABILITY platform data flag
  hwmon: (pmbus/ibm-cffps) Set the PMBUS_NO_CAPABILITY flag

 drivers/hwmon/pmbus/ibm-cffps.c  | 2 +-
 drivers/hwmon/pmbus/pmbus_core.c | 8 +---
 include/linux/pmbus.h| 9 +
 3 files changed, 15 insertions(+), 4 deletions(-)

-- 
2.27.0



Re: [PATCH 1/2] hwmon: (pmbus) Add a NO_PEC flag to probe chips with faulty CAPABILITY

2020-12-21 Thread Eddie James
On Mon, 2020-12-21 at 08:54 -0800, Guenter Roeck wrote:
> On 12/21/20 8:30 AM, Eddie James wrote:
> > Some PMBus chips don't respond with valid data when reading the
> > CAPABILITY register. For instance the register may report that the
> > chip supports PEC when in reality it does not. For such chips, PEC
> > must not be enabled while probing the chip, so add a flag so that
> > device drivers can force PEC off.
> > 
> 
> I think the flag should indicate that the capability register
> shall not be read/used. That the capability register is currently
> only used to check for PEC is secondary. We might,for example,
> start using it to check for alert support or to check the numeric
> format.

OK, that makes sense. I'll rename the flag in v2, how does
PMBUS_NO_CAPABILITY sound?

Thanks for the quick reply,
Eddie

> 
> Thanks,
> Guenter
> 
> > Signed-off-by: Eddie James 
> > ---
> >  drivers/hwmon/pmbus/pmbus_core.c |  8 +---
> >  include/linux/pmbus.h| 10 ++
> >  2 files changed, 15 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/hwmon/pmbus/pmbus_core.c
> > b/drivers/hwmon/pmbus/pmbus_core.c
> > index 192442b3b7a2..3de1657dde35 100644
> > --- a/drivers/hwmon/pmbus/pmbus_core.c
> > +++ b/drivers/hwmon/pmbus/pmbus_core.c
> > @@ -2204,9 +2204,11 @@ static int pmbus_init_common(struct
> > i2c_client *client, struct pmbus_data *data,
> > }
> >  
> > /* Enable PEC if the controller supports it */
> > -   ret = i2c_smbus_read_byte_data(client, PMBUS_CAPABILITY);
> > -   if (ret >= 0 && (ret & PB_CAPABILITY_ERROR_CHECK))
> > -   client->flags |= I2C_CLIENT_PEC;
> > +   if (!(data->flags & PMBUS_NO_PEC)) {
> > +   ret = i2c_smbus_read_byte_data(client,
> > PMBUS_CAPABILITY);
> > +   if (ret >= 0 && (ret & PB_CAPABILITY_ERROR_CHECK))
> > +   client->flags |= I2C_CLIENT_PEC;
> > +   }
> >  
> > /*
> >  * Check if the chip is write protected. If it is, we can not
> > clear
> > diff --git a/include/linux/pmbus.h b/include/linux/pmbus.h
> > index 1ea5bae708a1..9bdc8a581b03 100644
> > --- a/include/linux/pmbus.h
> > +++ b/include/linux/pmbus.h
> > @@ -34,6 +34,16 @@
> >   */
> >  #define PMBUS_WRITE_PROTECTED  BIT(1)
> >  
> > +/*
> > + * PMBUS_NO_PEC
> > + *
> > + * Some PMBus chips don't respond with valid data when reading the
> > CAPABILITY
> > + * register. In this case, the register may report that the chip
> > supports PEC
> > + * with bit 7 (PB_CAPABILITY_ERROR_CHECK) when in reality it's not
> > supported.
> > + * For such chips, PEC must not be enabled before probing the
> > chip.
> > + */
> > +#define PMBUS_NO_PEC   BIT(2)
> > +
> >  struct pmbus_platform_data {
> > u32 flags;  /* Device specific flags */
> >  
> > 



[PATCH 0/2] hwmon: (pmbus) Add a NO_PEC flag to probe chips with faulty CAPABILITY

2020-12-21 Thread Eddie James
Some PMBus chips don't respond with valid data when reading the
CAPABILITY register. For instance the register may report that the
chip supports PEC when in reality it does not. For such chips, PEC
must not be enabled while probing the chip, so this series adds a flag
that allows device drivers to force PEC off. The second patch enables
this flag for the IBM CFFPS driver, which supports power supplies that
report invalid in the CAPABILITY register and must therefore force PEC
off.

Eddie James (2):
  hwmon: (pmbus) Add a NO_PEC flag to probe chips with faulty CAPABILITY
  hwmon: (pmbus/ibm-cffps) Set the PMBUS_NO_PEC flag

 drivers/hwmon/pmbus/ibm-cffps.c  |  2 +-
 drivers/hwmon/pmbus/pmbus_core.c |  8 +---
 include/linux/pmbus.h| 10 ++
 3 files changed, 16 insertions(+), 4 deletions(-)

-- 
2.27.0



[PATCH 1/2] hwmon: (pmbus) Add a NO_PEC flag to probe chips with faulty CAPABILITY

2020-12-21 Thread Eddie James
Some PMBus chips don't respond with valid data when reading the
CAPABILITY register. For instance the register may report that the
chip supports PEC when in reality it does not. For such chips, PEC
must not be enabled while probing the chip, so add a flag so that
device drivers can force PEC off.

Signed-off-by: Eddie James 
---
 drivers/hwmon/pmbus/pmbus_core.c |  8 +---
 include/linux/pmbus.h| 10 ++
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 192442b3b7a2..3de1657dde35 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -2204,9 +2204,11 @@ static int pmbus_init_common(struct i2c_client *client, 
struct pmbus_data *data,
}
 
/* Enable PEC if the controller supports it */
-   ret = i2c_smbus_read_byte_data(client, PMBUS_CAPABILITY);
-   if (ret >= 0 && (ret & PB_CAPABILITY_ERROR_CHECK))
-   client->flags |= I2C_CLIENT_PEC;
+   if (!(data->flags & PMBUS_NO_PEC)) {
+   ret = i2c_smbus_read_byte_data(client, PMBUS_CAPABILITY);
+   if (ret >= 0 && (ret & PB_CAPABILITY_ERROR_CHECK))
+   client->flags |= I2C_CLIENT_PEC;
+   }
 
/*
 * Check if the chip is write protected. If it is, we can not clear
diff --git a/include/linux/pmbus.h b/include/linux/pmbus.h
index 1ea5bae708a1..9bdc8a581b03 100644
--- a/include/linux/pmbus.h
+++ b/include/linux/pmbus.h
@@ -34,6 +34,16 @@
  */
 #define PMBUS_WRITE_PROTECTED  BIT(1)
 
+/*
+ * PMBUS_NO_PEC
+ *
+ * Some PMBus chips don't respond with valid data when reading the CAPABILITY
+ * register. In this case, the register may report that the chip supports PEC
+ * with bit 7 (PB_CAPABILITY_ERROR_CHECK) when in reality it's not supported.
+ * For such chips, PEC must not be enabled before probing the chip.
+ */
+#define PMBUS_NO_PEC   BIT(2)
+
 struct pmbus_platform_data {
u32 flags;  /* Device specific flags */
 
-- 
2.27.0



[PATCH 2/2] hwmon: (pmbus/ibm-cffps) Set the PMBUS_NO_PEC flag

2020-12-21 Thread Eddie James
Several power supplies supported by the IBM CFFPS driver don't
report valid data in the CAPABILITY register, or support PEC only
for certain PMBus registers. Since the automatic version detection
of the driver might fail on some supplies with PEC enabled, just
disable PEC entirely for this driver.

Signed-off-by: Eddie James 
---
 drivers/hwmon/pmbus/ibm-cffps.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hwmon/pmbus/ibm-cffps.c b/drivers/hwmon/pmbus/ibm-cffps.c
index d6223871..f8e3ae989e99 100644
--- a/drivers/hwmon/pmbus/ibm-cffps.c
+++ b/drivers/hwmon/pmbus/ibm-cffps.c
@@ -472,7 +472,7 @@ static struct pmbus_driver_info ibm_cffps_info[] = {
 };
 
 static struct pmbus_platform_data ibm_cffps_pdata = {
-   .flags = PMBUS_SKIP_STATUS_CHECK,
+   .flags = PMBUS_SKIP_STATUS_CHECK | PMBUS_NO_PEC,
 };
 
 static int ibm_cffps_probe(struct i2c_client *client)
-- 
2.27.0



[PATCH] spi: fsi: Fix transfer returning without finalizing message

2020-11-10 Thread Eddie James
In the case that the SPI mux isn't set, the transfer_one_message
function returns without finalizing the message. This means that
the transfer never completes, resulting in hung tasks and an
eventual kernel panic. Fix it by finalizing the transfer in this
case.

Fixes: 9211a441e606 ("spi: fsi: Check mux status before transfers")
Signed-off-by: Eddie James 
---
 drivers/spi/spi-fsi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c
index 8a440c7078ef..3920cd3286d8 100644
--- a/drivers/spi/spi-fsi.c
+++ b/drivers/spi/spi-fsi.c
@@ -477,7 +477,7 @@ static int fsi_spi_transfer_one_message(struct 
spi_controller *ctlr,
 
rc = fsi_spi_check_mux(ctx->fsi, ctx->dev);
if (rc)
-   return rc;
+   goto error;
 
list_for_each_entry(transfer, >transfers, transfer_list) {
struct fsi_spi_sequence seq;
-- 
2.26.2



Re: [PATCH v3 3/5] i2c: aspeed: Mask IRQ status to relevant bits

2020-09-10 Thread Eddie James



On 9/10/20 4:00 AM, Brendan Higgins wrote:

On Wed, Sep 9, 2020 at 1:31 PM Eddie James  wrote:

Mask the IRQ status to only the bits that the driver checks. This
prevents excessive driver warnings when operating in slave mode
when additional bits are set that the driver doesn't handle.

Signed-off-by: Eddie James 
Reviewed-by: Tao Ren 

Sorry, looks like I didn't get my comment in in time.

Looks good in principle. One minor comment below:


---
  drivers/i2c/busses/i2c-aspeed.c | 2 ++
  1 file changed, 2 insertions(+)

diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
index 31268074c422..724bf30600d6 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -69,6 +69,7 @@
   * These share bit definitions, so use the same values for the enable &
   * status bits.
   */
+#define ASPEED_I2CD_INTR_RECV_MASK 0xf000

Could we define ASPEED_I2CD_INTR_RECV_MASK to be ASPEED_I2CD_INTR_ALL ?



That was my original thought... there is another define for that already 
a few lines down though.



Thanks,

Eddie





  #define ASPEED_I2CD_INTR_SDA_DL_TIMEOUTBIT(14)
  #define ASPEED_I2CD_INTR_BUS_RECOVER_DONE  BIT(13)
  #define ASPEED_I2CD_INTR_SLAVE_MATCH   BIT(7)
@@ -604,6 +605,7 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
 writel(irq_received & ~ASPEED_I2CD_INTR_RX_DONE,
bus->base + ASPEED_I2C_INTR_STS_REG);
 readl(bus->base + ASPEED_I2C_INTR_STS_REG);
+   irq_received &= ASPEED_I2CD_INTR_RECV_MASK;
 irq_remaining = irq_received;

  #if IS_ENABLED(CONFIG_I2C_SLAVE)
--
2.26.2



[PATCH 1/4] dt-bindings: clock: Add AST2600 APLLdivN definition

2020-09-10 Thread Eddie James
Add a new clock definition for the "APLLdivN" as described in the
AST2600 specification. This clock is simply the APLL divided by a
factor defined in the SCU registers. It is the input to the FSI
bus.

Signed-off-by: Eddie James 
---
 include/dt-bindings/clock/ast2600-clock.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/dt-bindings/clock/ast2600-clock.h 
b/include/dt-bindings/clock/ast2600-clock.h
index 62b9520a00fd..5a9ae0a1d574 100644
--- a/include/dt-bindings/clock/ast2600-clock.h
+++ b/include/dt-bindings/clock/ast2600-clock.h
@@ -87,6 +87,7 @@
 #define ASPEED_CLK_MAC2RCLK68
 #define ASPEED_CLK_MAC3RCLK69
 #define ASPEED_CLK_MAC4RCLK70
+#define ASPEED_CLK_APLLN   71
 
 /* Only list resets here that are not part of a gate */
 #define ASPEED_RESET_ADC   55
-- 
2.26.2



[PATCH 0/4] clk: AST2600 and FSI: Add APLL to control FSI bus frequency

2020-09-10 Thread Eddie James
Add functionality to control the APLL clock on the AST2600. The APLL provides
the clock for the FSI master on the AST2600. Then add a devicetree property to
set the AST2600 FSI master bus frequency.

Eddie James (4):
  dt-bindings: clock: Add AST2600 APLLdivN definition
  clk: ast2600: Add functionality to the APLL clock
  dt-bindings: fsi: Aspeed master: Add bus-frequency property
  fsi: Aspeed master: Set bus frequency from devicetree

 .../bindings/fsi/fsi-master-aspeed.txt|   1 +
 drivers/clk/clk-ast2600.c | 177 --
 drivers/fsi/fsi-master-aspeed.c   |   5 +
 include/dt-bindings/clock/ast2600-clock.h |   1 +
 4 files changed, 172 insertions(+), 12 deletions(-)

-- 
2.26.2



[PATCH 2/4] clk: ast2600: Add functionality to the APLL clock

2020-09-10 Thread Eddie James
Register a clock with it's own operations to describe the APLL on
the AST2600. The clock is controlled by an SCU register containing
a multiplier and divider of the 25MHz input clock.
The functionality to change the APLL is necessary to finely control
the FSI bus frequency.

Signed-off-by: Eddie James 
---
 drivers/clk/clk-ast2600.c | 177 +++---
 1 file changed, 165 insertions(+), 12 deletions(-)

diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c
index 177368cac6dd..a147dffbaccc 100644
--- a/drivers/clk/clk-ast2600.c
+++ b/drivers/clk/clk-ast2600.c
@@ -4,6 +4,7 @@
 
 #define pr_fmt(fmt) "clk-ast2600: " fmt
 
+#include 
 #include 
 #include 
 #include 
@@ -15,7 +16,7 @@
 
 #include "clk-aspeed.h"
 
-#define ASPEED_G6_NUM_CLKS 71
+#define ASPEED_G6_NUM_CLKS 72
 
 #define ASPEED_G6_SILICON_REV  0x004
 
@@ -31,6 +32,7 @@
 #define ASPEED_G6_CLK_SELECTION1   0x300
 #define ASPEED_G6_CLK_SELECTION2   0x304
 #define ASPEED_G6_CLK_SELECTION4   0x310
+#define ASPEED_G6_CLK_SELECTION5   0x314
 
 #define ASPEED_HPLL_PARAM  0x200
 #define ASPEED_APLL_PARAM  0x210
@@ -116,7 +118,7 @@ static const struct aspeed_gate_data aspeed_g6_gates[] = {
[ASPEED_CLK_GATE_UART11CLK] = { 59,  -1, "uart11clk-gate",  
"uartx", 0 },   /* UART11 */
[ASPEED_CLK_GATE_UART12CLK] = { 60,  -1, "uart12clk-gate",  
"uartx", 0 },   /* UART12 */
[ASPEED_CLK_GATE_UART13CLK] = { 61,  -1, "uart13clk-gate",  
"uartx", 0 },   /* UART13 */
-   [ASPEED_CLK_GATE_FSICLK]= { 62,  59, "fsiclk-gate", NULL,   
 0 },   /* FSI */
+   [ASPEED_CLK_GATE_FSICLK]= { 62,  59, "fsiclk-gate", 
"aplln", CLK_SET_RATE_PARENT }, /* FSI */
 };
 
 static const struct clk_div_table ast2600_eclk_div_table[] = {
@@ -187,24 +189,166 @@ static struct clk_hw *ast2600_calc_pll(const char *name, 
u32 val)
mult, div);
 };
 
-static struct clk_hw *ast2600_calc_apll(const char *name, u32 val)
+/*
+ * APLL Frequency: F = 25MHz * (2 - od) * [(m + 2) / (n + 1)]
+ */
+static void ast2600_apll_get_params(unsigned int *div, unsigned int *mul)
 {
-   unsigned int mult, div;
+   u32 val = readl(scu_g6_base + ASPEED_APLL_PARAM);
 
if (val & BIT(20)) {
/* Pass through mode */
-   mult = div = 1;
+   *mul = *div = 1;
} else {
-   /* F = 25Mhz * (2-od) * [(m + 2) / (n + 1)] */
u32 m = (val >> 5) & 0x3f;
u32 od = (val >> 4) & 0x1;
u32 n = val & 0xf;
 
-   mult = (2 - od) * (m + 2);
-   div = n + 1;
+   *mul = (2 - od) * (m + 2);
+   *div = n + 1;
}
-   return clk_hw_register_fixed_factor(NULL, name, "clkin", 0,
-   mult, div);
+}
+
+static long ast2600_apll_best(unsigned long ul_rate, unsigned long ul_prate,
+ unsigned int *out_div, unsigned int *out_mul,
+ unsigned int *output_divider)
+{
+#define min_mult 2ULL
+#define max_mult 65ULL
+#define min_div 1ULL
+#define max_div 16ULL
+   int i;
+   unsigned int bod = 0;
+   unsigned long long rem = 1ULL;
+   unsigned long long brem = ~(0ULL);
+   unsigned long long bdiv = 1ULL;
+   unsigned long long tdiv;
+   unsigned long long bmul = 16ULL;
+   unsigned long long tmul;
+   long brate = -ERANGE;
+   unsigned long long trate;
+   unsigned long long rate = ul_rate;
+   unsigned long long prate = ul_prate;
+
+   for (i = 0; i < 2; ++i, prate *= 2ULL) {
+   for (tdiv = min_div; tdiv <= max_div; ++tdiv) {
+   tmul = DIV_ROUND_CLOSEST_ULL(rate * tdiv, prate);
+   if (tmul <  min_mult || tmul > max_mult)
+   continue;
+
+   trate = DIV_ROUND_CLOSEST_ULL(prate * tmul, tdiv);
+   if (trate > rate)
+   rem = trate - rate;
+   else
+   rem = rate - trate;
+
+   if (rem < brem) {
+   bod = !i;
+   brem = rem;
+   bdiv = tdiv;
+   bmul = tmul;
+   brate = (long)trate;
+   }
+
+   if (!rem)
+   break;
+   }
+
+   if (!rem)
+   break;
+   }
+
+   if (out_div)
+   *out_div = (unsigned int)bdiv;
+
+   if (out_mul)
+   *out_mul = (unsigned int)bmul;
+
+   if (output_divider)
+ 

[PATCH 3/4] dt-bindings: fsi: Aspeed master: Add bus-frequency property

2020-09-10 Thread Eddie James
Document the bus-frequency property.

Signed-off-by: Eddie James 
---
 Documentation/devicetree/bindings/fsi/fsi-master-aspeed.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/fsi/fsi-master-aspeed.txt 
b/Documentation/devicetree/bindings/fsi/fsi-master-aspeed.txt
index a513e65ec0c9..d84bd19526ca 100644
--- a/Documentation/devicetree/bindings/fsi/fsi-master-aspeed.txt
+++ b/Documentation/devicetree/bindings/fsi/fsi-master-aspeed.txt
@@ -17,6 +17,7 @@ Optional properties:
 
  - fsi-routing-gpios: GPIO for setting the FSI mux (internal or cabled)
  - fsi-mux-gpios: GPIO for detecting the desired FSI mux state
+ - bus-frequency: the frequency of the FSI bus
 
 
 Examples:
-- 
2.26.2



[PATCH 4/4] fsi: Aspeed master: Set bus frequency from devicetree

2020-09-10 Thread Eddie James
Set the FSI bus frequency based on the value encoded in the
devicetree. The default value is 166MHz, which is the highest
frequency some FSI slaves can accept.

Signed-off-by: Eddie James 
Reviewed-by: Joel Stanley 
---
 drivers/fsi/fsi-master-aspeed.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/fsi/fsi-master-aspeed.c b/drivers/fsi/fsi-master-aspeed.c
index c006ec008a1a..be19fee0bece 100644
--- a/drivers/fsi/fsi-master-aspeed.c
+++ b/drivers/fsi/fsi-master-aspeed.c
@@ -515,6 +515,7 @@ static int fsi_master_aspeed_probe(struct platform_device 
*pdev)
struct fsi_master_aspeed *aspeed;
struct resource *res;
int rc, links, reg;
+   u32 bus_freq = 1;
__be32 raw;
 
rc = tacoma_cabled_fsi_fixup(>dev);
@@ -539,6 +540,10 @@ static int fsi_master_aspeed_probe(struct platform_device 
*pdev)
dev_err(aspeed->dev, "couldn't get clock\n");
return PTR_ERR(aspeed->clk);
}
+
+   of_property_read_u32(pdev->dev.of_node, "bus-frequency", _freq);
+   clk_set_rate(aspeed->clk, bus_freq);
+
rc = clk_prepare_enable(aspeed->clk);
if (rc) {
dev_err(aspeed->dev, "couldn't enable clock\n");
-- 
2.26.2



[PATCH v2 1/6] spi: fsi: Handle 9 to 15 byte transfers lengths

2020-09-09 Thread Eddie James
From: Brad Bishop 

The trailing  - 8 bytes of transfer data in this size range is no
longer ignored.

Fixes: bbb6b2f9865b ("spi: Add FSI-attached SPI controller driver")
Signed-off-by: Brad Bishop 
Signed-off-by: Eddie James 
Reviewed-by: Joel Stanley 
Signed-off-by: Joel Stanley 
---
 drivers/spi/spi-fsi.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c
index 37a3e0f8e752..8f64af0140e0 100644
--- a/drivers/spi/spi-fsi.c
+++ b/drivers/spi/spi-fsi.c
@@ -258,15 +258,15 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
if (loops > 1) {
fsi_spi_sequence_add(seq, SPI_FSI_SEQUENCE_BRANCH(idx));
 
-   if (rem)
-   fsi_spi_sequence_add(seq, rem);
-
rc = fsi_spi_write_reg(ctx, SPI_FSI_COUNTER_CFG,
   SPI_FSI_COUNTER_CFG_LOOPS(loops - 1));
if (rc)
return rc;
}
 
+   if (rem)
+   fsi_spi_sequence_add(seq, rem);
+
return 0;
 }
 
-- 
2.26.2



[PATCH v2 6/6] spi: fsi: Check mux status before transfers

2020-09-09 Thread Eddie James
The SPI controllers are not accessible if the mux isn't set. Therefore,
check the mux status before starting a transfer and fail out if it isn't
set.

Signed-off-by: Eddie James 
Signed-off-by: Joel Stanley 
---
 drivers/spi/spi-fsi.c | 40 +++-
 1 file changed, 27 insertions(+), 13 deletions(-)

diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c
index a702e9d7d68c..8a440c7078ef 100644
--- a/drivers/spi/spi-fsi.c
+++ b/drivers/spi/spi-fsi.c
@@ -12,6 +12,7 @@
 
 #define FSI_ENGID_SPI  0x23
 #define FSI_MBOX_ROOT_CTRL_8   0x2860
+#define  FSI_MBOX_ROOT_CTRL_8_SPI_MUX   0xf000
 
 #define FSI2SPI_DATA0  0x00
 #define FSI2SPI_DATA1  0x04
@@ -84,6 +85,26 @@ struct fsi_spi_sequence {
u64 data;
 };
 
+static int fsi_spi_check_mux(struct fsi_device *fsi, struct device *dev)
+{
+   int rc;
+   u32 root_ctrl_8;
+   __be32 root_ctrl_8_be;
+
+   rc = fsi_slave_read(fsi->slave, FSI_MBOX_ROOT_CTRL_8, _ctrl_8_be,
+   sizeof(root_ctrl_8_be));
+   if (rc)
+   return rc;
+
+   root_ctrl_8 = be32_to_cpu(root_ctrl_8_be);
+   dev_dbg(dev, "Root control register 8: %08x\n", root_ctrl_8);
+   if ((root_ctrl_8 & FSI_MBOX_ROOT_CTRL_8_SPI_MUX) ==
+FSI_MBOX_ROOT_CTRL_8_SPI_MUX)
+   return 0;
+
+   return -ENOLINK;
+}
+
 static int fsi_spi_check_status(struct fsi_spi *ctx)
 {
int rc;
@@ -449,11 +470,15 @@ static int fsi_spi_transfer_init(struct fsi_spi *ctx)
 static int fsi_spi_transfer_one_message(struct spi_controller *ctlr,
struct spi_message *mesg)
 {
-   int rc = 0;
+   int rc;
u8 seq_slave = SPI_FSI_SEQUENCE_SEL_SLAVE(mesg->spi->chip_select + 1);
struct spi_transfer *transfer;
struct fsi_spi *ctx = spi_controller_get_devdata(ctlr);
 
+   rc = fsi_spi_check_mux(ctx->fsi, ctx->dev);
+   if (rc)
+   return rc;
+
list_for_each_entry(transfer, >transfers, transfer_list) {
struct fsi_spi_sequence seq;
struct spi_transfer *next = NULL;
@@ -537,24 +562,13 @@ static size_t fsi_spi_max_transfer_size(struct spi_device 
*spi)
 static int fsi_spi_probe(struct device *dev)
 {
int rc;
-   u32 root_ctrl_8;
struct device_node *np;
int num_controllers_registered = 0;
struct fsi_device *fsi = to_fsi_dev(dev);
 
-   /*
-* Check the SPI mux before attempting to probe. If the mux isn't set
-* then the SPI controllers can't access their slave devices.
-*/
-   rc = fsi_slave_read(fsi->slave, FSI_MBOX_ROOT_CTRL_8, _ctrl_8,
-   sizeof(root_ctrl_8));
+   rc = fsi_spi_check_mux(fsi, dev);
if (rc)
-   return rc;
-
-   if (!root_ctrl_8) {
-   dev_dbg(dev, "SPI mux not set, aborting probe.\n");
return -ENODEV;
-   }
 
for_each_available_child_of_node(dev->of_node, np) {
u32 base;
-- 
2.26.2



[PATCH v2 2/6] spi: fsi: Fix clock running too fast

2020-09-09 Thread Eddie James
From: Brad Bishop 

Use a clock divider tuned to a 200MHz FSI bus frequency (the maximum). Use
of the previous divider at 200MHz results in corrupt data from endpoint
devices. Ideally the clock divider would be calculated from the FSI clock,
but that would require some significant work on the FSI driver. With FSI
frequencies slower than 200MHz, the SPI clock will simply run slower, but
safely.

Signed-off-by: Brad Bishop 
Signed-off-by: Eddie James 
Signed-off-by: Joel Stanley 
---
 drivers/spi/spi-fsi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c
index 8f64af0140e0..559d0ff981f3 100644
--- a/drivers/spi/spi-fsi.c
+++ b/drivers/spi/spi-fsi.c
@@ -350,7 +350,7 @@ static int fsi_spi_transfer_init(struct fsi_spi *ctx)
u64 status = 0ULL;
u64 wanted_clock_cfg = SPI_FSI_CLOCK_CFG_ECC_DISABLE |
SPI_FSI_CLOCK_CFG_SCK_NO_DEL |
-   FIELD_PREP(SPI_FSI_CLOCK_CFG_SCK_DIV, 4);
+   FIELD_PREP(SPI_FSI_CLOCK_CFG_SCK_DIV, 19);
 
end = jiffies + msecs_to_jiffies(SPI_FSI_INIT_TIMEOUT_MS);
do {
-- 
2.26.2



[PATCH v2 4/6] dt-bindings: fsi: fsi2spi: Add compatible string for restricted version

2020-09-09 Thread Eddie James
Add a compatible string for the restricted version of the SPI controller.
The restricted version cannot process sequence loop operations and
therefore has a smaller transfer size.

Signed-off-by: Eddie James 
---
 Documentation/devicetree/bindings/fsi/ibm,fsi2spi.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/fsi/ibm,fsi2spi.yaml 
b/Documentation/devicetree/bindings/fsi/ibm,fsi2spi.yaml
index b26d4b4be743..fe39ea4904c1 100644
--- a/Documentation/devicetree/bindings/fsi/ibm,fsi2spi.yaml
+++ b/Documentation/devicetree/bindings/fsi/ibm,fsi2spi.yaml
@@ -19,6 +19,7 @@ properties:
   compatible:
 enum:
   - ibm,fsi2spi
+  - ibm,fsi2spi-restricted
 
   reg:
 items:
-- 
2.26.2



[PATCH v2 3/6] spi: fsi: Fix use of the bneq+ sequencer instruction

2020-09-09 Thread Eddie James
From: Brad Bishop 

All of the switches in N2_count_control in the counter configuration are
required to make the branch if not equal and increment command work.
Set them when using bneq+.

A side effect of this mode requires a dummy write to TDR when both
transmitting and receiving otherwise the controller won't start shifting
receive data.

It is likely not possible to avoid TDR underrun errors in this mode and
they are harmless, so do not check for them.

Fixes: bbb6b2f9865b ("spi: Add FSI-attached SPI controller driver")
Signed-off-by: Brad Bishop 
Signed-off-by: Eddie James 
Reviewed-by: Joel Stanley 
Signed-off-by: Joel Stanley 
---
 drivers/spi/spi-fsi.c | 28 +---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c
index 559d0ff981f3..c31a852b6a3e 100644
--- a/drivers/spi/spi-fsi.c
+++ b/drivers/spi/spi-fsi.c
@@ -29,6 +29,10 @@
 #define SPI_FSI_ERROR  0x0
 #define SPI_FSI_COUNTER_CFG0x1
 #define  SPI_FSI_COUNTER_CFG_LOOPS(x)   (((u64)(x) & 0xffULL) << 32)
+#define  SPI_FSI_COUNTER_CFG_N2_RX  BIT_ULL(8)
+#define  SPI_FSI_COUNTER_CFG_N2_TX  BIT_ULL(9)
+#define  SPI_FSI_COUNTER_CFG_N2_IMPLICIT BIT_ULL(10)
+#define  SPI_FSI_COUNTER_CFG_N2_RELOAD  BIT_ULL(11)
 #define SPI_FSI_CFG1   0x2
 #define SPI_FSI_CLOCK_CFG  0x3
 #define  SPI_FSI_CLOCK_CFG_MM_ENABLEBIT_ULL(32)
@@ -61,7 +65,7 @@
 #define  SPI_FSI_STATUS_RDR_OVERRUN BIT_ULL(62)
 #define  SPI_FSI_STATUS_RDR_FULLBIT_ULL(63)
 #define  SPI_FSI_STATUS_ANY_ERROR   \
-   (SPI_FSI_STATUS_ERROR | SPI_FSI_STATUS_TDR_UNDERRUN | \
+   (SPI_FSI_STATUS_ERROR | \
 SPI_FSI_STATUS_TDR_OVERRUN | SPI_FSI_STATUS_RDR_UNDERRUN | \
 SPI_FSI_STATUS_RDR_OVERRUN)
 #define SPI_FSI_PORT_CTRL  0x9
@@ -238,6 +242,7 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
int rc;
u8 len = min(transfer->len, 8U);
u8 rem = transfer->len % len;
+   u64 cfg = 0ULL;
 
loops = transfer->len / len;
 
@@ -258,8 +263,14 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
if (loops > 1) {
fsi_spi_sequence_add(seq, SPI_FSI_SEQUENCE_BRANCH(idx));
 
-   rc = fsi_spi_write_reg(ctx, SPI_FSI_COUNTER_CFG,
-  SPI_FSI_COUNTER_CFG_LOOPS(loops - 1));
+   cfg = SPI_FSI_COUNTER_CFG_LOOPS(loops - 1);
+   if (transfer->rx_buf)
+   cfg |= SPI_FSI_COUNTER_CFG_N2_RX |
+   SPI_FSI_COUNTER_CFG_N2_TX |
+   SPI_FSI_COUNTER_CFG_N2_IMPLICIT |
+   SPI_FSI_COUNTER_CFG_N2_RELOAD;
+
+   rc = fsi_spi_write_reg(ctx, SPI_FSI_COUNTER_CFG, cfg);
if (rc)
return rc;
}
@@ -275,6 +286,7 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx,
 {
int rc = 0;
u64 status = 0ULL;
+   u64 cfg = 0ULL;
 
if (transfer->tx_buf) {
int nb;
@@ -312,6 +324,16 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx,
u64 in = 0ULL;
u8 *rx = transfer->rx_buf;
 
+   rc = fsi_spi_read_reg(ctx, SPI_FSI_COUNTER_CFG, );
+   if (rc)
+   return rc;
+
+   if (cfg & SPI_FSI_COUNTER_CFG_N2_IMPLICIT) {
+   rc = fsi_spi_write_reg(ctx, SPI_FSI_DATA_TX, 0);
+   if (rc)
+   return rc;
+   }
+
while (transfer->len > recv) {
do {
rc = fsi_spi_read_reg(ctx, SPI_FSI_STATUS,
-- 
2.26.2



[PATCH v2 5/6] spi: fsi: Implement restricted size for certain controllers

2020-09-09 Thread Eddie James
Some of the FSI-attached SPI controllers cannot use the loop command in
programming the sequencer due to security requirements. Check the
devicetree compatibility that indicates this condition and restrict the
size for these controllers. Also, add more transfers directly in the
sequence up to the length of the sequence register.

Fixes: bbb6b2f9865b ("spi: Add FSI-attached SPI controller driver")
Signed-off-by: Eddie James 
Reviewed-by: Joel Stanley 
Signed-off-by: Joel Stanley 
---
 drivers/spi/spi-fsi.c | 65 +++
 1 file changed, 53 insertions(+), 12 deletions(-)

diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c
index c31a852b6a3e..a702e9d7d68c 100644
--- a/drivers/spi/spi-fsi.c
+++ b/drivers/spi/spi-fsi.c
@@ -24,7 +24,8 @@
 
 #define SPI_FSI_BASE   0x7
 #define SPI_FSI_INIT_TIMEOUT_MS1000
-#define SPI_FSI_MAX_TRANSFER_SIZE  2048
+#define SPI_FSI_MAX_XFR_SIZE   2048
+#define SPI_FSI_MAX_XFR_SIZE_RESTRICTED32
 
 #define SPI_FSI_ERROR  0x0
 #define SPI_FSI_COUNTER_CFG0x1
@@ -74,6 +75,8 @@ struct fsi_spi {
struct device *dev; /* SPI controller device */
struct fsi_device *fsi; /* FSI2SPI CFAM engine device */
u32 base;
+   size_t max_xfr_size;
+   bool restricted;
 };
 
 struct fsi_spi_sequence {
@@ -209,8 +212,12 @@ static int fsi_spi_reset(struct fsi_spi *ctx)
if (rc)
return rc;
 
-   return fsi_spi_write_reg(ctx, SPI_FSI_CLOCK_CFG,
-SPI_FSI_CLOCK_CFG_RESET2);
+   rc = fsi_spi_write_reg(ctx, SPI_FSI_CLOCK_CFG,
+  SPI_FSI_CLOCK_CFG_RESET2);
+   if (rc)
+   return rc;
+
+   return fsi_spi_write_reg(ctx, SPI_FSI_STATUS, 0ULL);
 }
 
 static int fsi_spi_sequence_add(struct fsi_spi_sequence *seq, u8 val)
@@ -218,8 +225,8 @@ static int fsi_spi_sequence_add(struct fsi_spi_sequence 
*seq, u8 val)
/*
 * Add the next byte of instruction to the 8-byte sequence register.
 * Then decrement the counter so that the next instruction will go in
-* the right place. Return the number of "slots" left in the sequence
-* register.
+* the right place. Return the index of the slot we just filled in the
+* sequence register.
 */
seq->data |= (u64)val << seq->bit;
seq->bit -= 8;
@@ -237,9 +244,11 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
 struct fsi_spi_sequence *seq,
 struct spi_transfer *transfer)
 {
+   bool docfg = false;
int loops;
int idx;
int rc;
+   u8 val = 0;
u8 len = min(transfer->len, 8U);
u8 rem = transfer->len % len;
u64 cfg = 0ULL;
@@ -247,22 +256,42 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
loops = transfer->len / len;
 
if (transfer->tx_buf) {
-   idx = fsi_spi_sequence_add(seq,
-  SPI_FSI_SEQUENCE_SHIFT_OUT(len));
+   val = SPI_FSI_SEQUENCE_SHIFT_OUT(len);
+   idx = fsi_spi_sequence_add(seq, val);
+
if (rem)
rem = SPI_FSI_SEQUENCE_SHIFT_OUT(rem);
} else if (transfer->rx_buf) {
-   idx = fsi_spi_sequence_add(seq,
-  SPI_FSI_SEQUENCE_SHIFT_IN(len));
+   val = SPI_FSI_SEQUENCE_SHIFT_IN(len);
+   idx = fsi_spi_sequence_add(seq, val);
+
if (rem)
rem = SPI_FSI_SEQUENCE_SHIFT_IN(rem);
} else {
return -EINVAL;
}
 
+   if (ctx->restricted) {
+   const int eidx = rem ? 5 : 6;
+
+   while (loops > 1 && idx <= eidx) {
+   idx = fsi_spi_sequence_add(seq, val);
+   loops--;
+   docfg = true;
+   }
+
+   if (loops > 1) {
+   dev_warn(ctx->dev, "No sequencer slots; aborting.\n");
+   return -EINVAL;
+   }
+   }
+
if (loops > 1) {
fsi_spi_sequence_add(seq, SPI_FSI_SEQUENCE_BRANCH(idx));
+   docfg = true;
+   }
 
+   if (docfg) {
cfg = SPI_FSI_COUNTER_CFG_LOOPS(loops - 1);
if (transfer->rx_buf)
cfg |= SPI_FSI_COUNTER_CFG_N2_RX |
@@ -273,6 +302,8 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
rc = fsi_spi_write_reg(ctx, SPI_FSI_COUNTER_CFG, cfg);
if (rc)
return rc;
+   } else {
+   fsi_spi_write_reg(ctx, SPI_FSI_COUNTER_CFG, 0ULL);
}
 
if (rem)
@@ -429,7 +460,7 @@ static int fsi_s

[PATCH v2 0/6] spi: Fixes for FSI-attached controller

2020-09-09 Thread Eddie James
This series implements a number of fixes for the FSI-attached SPI
controller driver.

Changes since v1:
 - Switch to a new compatible string for the restricted version of the
   SPI controller, rather than a new boolean parameter.

Brad Bishop (3):
  spi: fsi: Handle 9 to 15 byte transfers lengths
  spi: fsi: Fix clock running too fast
  spi: fsi: Fix use of the bneq+ sequencer instruction

Eddie James (3):
  dt-bindings: fsi: fsi2spi: Add compatible string for restricted
version
  spi: fsi: Implement restricted size for certain controllers
  spi: fsi: Check mux status before transfers

 .../devicetree/bindings/fsi/ibm,fsi2spi.yaml  |   1 +
 drivers/spi/spi-fsi.c | 139 ++
 2 files changed, 109 insertions(+), 31 deletions(-)

-- 
2.26.2



[PATCH v3 2/5] input: misc: Add IBM Operation Panel driver

2020-09-09 Thread Eddie James
Add a driver to get the button events from the panel and provide
them to userspace with the input subsystem. The panel is
connected with I2C and controls the bus, so the driver registers
as an I2C slave device.

Signed-off-by: Eddie James 
Reviewed-by: Joel Stanley 
---
 MAINTAINERS|   1 +
 drivers/input/misc/Kconfig |  18 
 drivers/input/misc/Makefile|   1 +
 drivers/input/misc/ibm-panel.c | 189 +
 4 files changed, 209 insertions(+)
 create mode 100644 drivers/input/misc/ibm-panel.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 28408d29d873..5429da957a1a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8351,6 +8351,7 @@ M:Eddie James 
 L: linux-in...@vger.kernel.org
 S: Maintained
 F: Documentation/devicetree/bindings/input/ibm,op-panel.yaml
+F: drivers/input/misc/ibm-panel.c
 
 IBM Power 842 compression accelerator
 M: Haren Myneni 
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 362e8a01980c..65ab1ce7b259 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -708,6 +708,24 @@ config INPUT_ADXL34X_SPI
  To compile this driver as a module, choose M here: the
  module will be called adxl34x-spi.
 
+config INPUT_IBM_PANEL
+   tristate "IBM Operation Panel driver"
+   depends on I2C_SLAVE || COMPILE_TEST
+   help
+ Say Y here if you have an IBM Operation Panel connected to your system
+ over I2C. The panel is typically connected only to a system's service
+ processor (BMC).
+
+ If unsure, say N.
+
+ The Operation Panel is a controller with some buttons and an LCD
+ display that allows someone with physical access to the system to
+ perform various administrative tasks. This driver only supports the 
part
+ of the controller that sends commands to the system.
+
+ To compile this driver as a module, choose M here: the module will be
+ called ibm-panel.
+
 config INPUT_IMS_PCU
tristate "IMS Passenger Control Unit driver"
depends on USB
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index a48e5f2d859d..7e9edf0a142b 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_INPUT_GPIO_DECODER)  += gpio_decoder.o
 obj-$(CONFIG_INPUT_GPIO_VIBRA) += gpio-vibra.o
 obj-$(CONFIG_INPUT_HISI_POWERKEY)  += hisi_powerkey.o
 obj-$(CONFIG_HP_SDC_RTC)   += hp_sdc_rtc.o
+obj-$(CONFIG_INPUT_IBM_PANEL)  += ibm-panel.o
 obj-$(CONFIG_INPUT_IMS_PCU)+= ims-pcu.o
 obj-$(CONFIG_INPUT_IQS269A)+= iqs269a.o
 obj-$(CONFIG_INPUT_IXP4XX_BEEPER)  += ixp4xx-beeper.o
diff --git a/drivers/input/misc/ibm-panel.c b/drivers/input/misc/ibm-panel.c
new file mode 100644
index ..7329f4641636
--- /dev/null
+++ b/drivers/input/misc/ibm-panel.c
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) IBM Corporation 2020
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEVICE_NAME"ibm-panel"
+
+struct ibm_panel {
+   u8 idx;
+   u8 command[11];
+   spinlock_t lock;/* protects writes to idx and command */
+   struct input_dev *input;
+};
+
+static void ibm_panel_process_command(struct ibm_panel *panel)
+{
+   u8 i;
+   u8 chksum;
+   u16 sum = 0;
+   int pressed;
+   int released;
+
+   if (panel->command[0] != 0xff && panel->command[1] != 0xf0) {
+   dev_dbg(>input->dev, "command invalid\n");
+   return;
+   }
+
+   for (i = 0; i < sizeof(panel->command) - 1; ++i) {
+   sum += panel->command[i];
+   if (sum & 0xff00) {
+   sum &= 0xff;
+   sum++;
+   }
+   }
+
+   chksum = sum & 0xff;
+   chksum = ~chksum;
+   chksum++;
+
+   if (chksum != panel->command[sizeof(panel->command) - 1]) {
+   dev_dbg(>input->dev, "command failed checksum\n");
+   return;
+   }
+
+   released = panel->command[2] & 0x80;
+   pressed = released ? 0 : 1;
+
+   switch (panel->command[2] & 0xf) {
+   case 0:
+   input_report_key(panel->input, BTN_NORTH, pressed);
+   break;
+   case 1:
+   input_report_key(panel->input, BTN_SOUTH, pressed);
+   break;
+   case 2:
+   input_report_key(panel->input, BTN_SELECT, pressed);
+   break;
+   default:
+   dev_dbg(>input->dev, "unknown command %u\n",
+   panel->command[2] & 0xf);
+   return;
+   }
+
+   input_sync(panel->input);
+}
+
+static int

[PATCH v3 5/5] ARM: dts: Aspeed: Rainier: Add IBM Operation Panel I2C device

2020-09-09 Thread Eddie James
Set I2C bus 7 to multi-master mode and add the panel device that will
register as a slave.

Signed-off-by: Eddie James 
Reviewed-by: Joel Stanley 
---
 arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts 
b/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
index b94421f6cbd5..50d528444f5d 100644
--- a/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
@@ -4,6 +4,7 @@
 
 #include "aspeed-g6.dtsi"
 #include 
+#include 
 #include 
 
 / {
@@ -698,6 +699,7 @@ eeprom@53 {
 };
 
  {
+   multi-master;
status = "okay";
 
si7021-a20@20 {
@@ -831,6 +833,11 @@ gpio@15 {
};
};
 
+   ibm-panel@62 {
+   compatible = "ibm,op-panel";
+   reg = <(0x62 | I2C_OWN_SLAVE_ADDRESS)>;
+   };
+
dps: dps310@76 {
compatible = "infineon,dps310";
reg = <0x76>;
-- 
2.26.2



[PATCH v3 4/5] ARM: dts: Aspeed: Tacoma: Add IBM Operation Panel I2C device

2020-09-09 Thread Eddie James
Set I2C bus 0 to multi-master mode and add the panel device that will
register as a slave.

Signed-off-by: Eddie James 
Reviewed-by: Joel Stanley 
---
 arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts 
b/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts
index 5f4ee67ac787..4d070d6ba09f 100644
--- a/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts
@@ -4,6 +4,7 @@
 
 #include "aspeed-g6.dtsi"
 #include 
+#include 
 #include 
 
 / {
@@ -438,7 +439,13 @@ aliases {
 };
 
  {
+   multi-master;
status = "okay";
+
+   ibm-panel@62 {
+   compatible = "ibm,op-panel";
+   reg = <(0x62 | I2C_OWN_SLAVE_ADDRESS)>;
+   };
 };
 
  {
-- 
2.26.2



[PATCH v3 0/5] input: misc: Add IBM Operation Panel driver

2020-09-09 Thread Eddie James
This series adds support for input from the IBM Operation Panel, which is
a simple controller with three buttons and an LCD display meant for
interacting with a server. It's connected over I2C, typically to a service
processor. This series only supports the input from the panel, in which the
panel masters the I2C bus and sends data to the host system when someone
presses a button on the controller.

Changes since v2:
 - Add "additionalProperties: false" to dts doc
 - Refactor switch statement in the input driver; check command size and call
   the processing function within the STOP case
 - Use a different definition name for Aspeed interrupt status mask

Changes since v1:
 - Redo DTS documentation example to use I2C_OWN_SLAVE_ADDRESS
 - Reject commands received in the input driver that are too long
 - Add a definition for the interrupt status mask in the Aspeed I2C driver
 - Use I2C_OWN_SLAVE_ADDRESS for both dts additions

Eddie James (5):
  dt-bindings: input: Add documentation for IBM Operation Panel
  input: misc: Add IBM Operation Panel driver
  i2c: aspeed: Mask IRQ status to relevant bits
  ARM: dts: Aspeed: Tacoma: Add IBM Operation Panel I2C device
  ARM: dts: Aspeed: Rainier: Add IBM Operation Panel I2C device

 .../bindings/input/ibm,op-panel.yaml  |  41 
 MAINTAINERS   |   7 +
 arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts  |   7 +
 arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts   |   7 +
 drivers/i2c/busses/i2c-aspeed.c   |   2 +
 drivers/input/misc/Kconfig|  18 ++
 drivers/input/misc/Makefile   |   1 +
 drivers/input/misc/ibm-panel.c| 189 ++
 8 files changed, 272 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/input/ibm,op-panel.yaml
 create mode 100644 drivers/input/misc/ibm-panel.c

-- 
2.26.2



[PATCH v3 1/5] dt-bindings: input: Add documentation for IBM Operation Panel

2020-09-09 Thread Eddie James
Document the bindings for the IBM Operation Panel, which provides
a simple interface to control a server. It has a display and three
buttons.
Also update MAINTAINERS for the new file.

Signed-off-by: Eddie James 
Reviewed-by: Rob Herring 
Acked-by: Joel Stanley 
---
 .../bindings/input/ibm,op-panel.yaml  | 41 +++
 MAINTAINERS   |  6 +++
 2 files changed, 47 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/input/ibm,op-panel.yaml

diff --git a/Documentation/devicetree/bindings/input/ibm,op-panel.yaml 
b/Documentation/devicetree/bindings/input/ibm,op-panel.yaml
new file mode 100644
index ..52c4a6275a77
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/ibm,op-panel.yaml
@@ -0,0 +1,41 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/ibm,op-panel.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: IBM Operation Panel
+
+maintainers:
+  - Eddie James 
+
+description: |
+  The IBM Operation Panel provides a simple interface to control the connected
+  server. It has a display and three buttons: two directional arrows and one
+  'Enter' button.
+
+properties:
+  compatible:
+const: ibm,op-panel
+
+  reg:
+maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+i2c {
+#address-cells = <1>;
+#size-cells = <0>;
+
+ibm-op-panel@62 {
+compatible = "ibm,op-panel";
+reg = <(0x62 | I2C_OWN_SLAVE_ADDRESS)>;
+};
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index 3c0692404907..28408d29d873 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8346,6 +8346,12 @@ T:   git 
git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux.git
 F: Documentation/ia64/
 F: arch/ia64/
 
+IBM Operation Panel Input Driver
+M: Eddie James 
+L: linux-in...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/input/ibm,op-panel.yaml
+
 IBM Power 842 compression accelerator
 M: Haren Myneni 
 S: Supported
-- 
2.26.2



[PATCH v3 3/5] i2c: aspeed: Mask IRQ status to relevant bits

2020-09-09 Thread Eddie James
Mask the IRQ status to only the bits that the driver checks. This
prevents excessive driver warnings when operating in slave mode
when additional bits are set that the driver doesn't handle.

Signed-off-by: Eddie James 
Reviewed-by: Tao Ren 
---
 drivers/i2c/busses/i2c-aspeed.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
index 31268074c422..724bf30600d6 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -69,6 +69,7 @@
  * These share bit definitions, so use the same values for the enable &
  * status bits.
  */
+#define ASPEED_I2CD_INTR_RECV_MASK 0xf000
 #define ASPEED_I2CD_INTR_SDA_DL_TIMEOUTBIT(14)
 #define ASPEED_I2CD_INTR_BUS_RECOVER_DONE  BIT(13)
 #define ASPEED_I2CD_INTR_SLAVE_MATCH   BIT(7)
@@ -604,6 +605,7 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
writel(irq_received & ~ASPEED_I2CD_INTR_RX_DONE,
   bus->base + ASPEED_I2C_INTR_STS_REG);
readl(bus->base + ASPEED_I2C_INTR_STS_REG);
+   irq_received &= ASPEED_I2CD_INTR_RECV_MASK;
irq_remaining = irq_received;
 
 #if IS_ENABLED(CONFIG_I2C_SLAVE)
-- 
2.26.2



[PATCH v2 3/5] i2c: aspeed: Mask IRQ status to relevant bits

2020-09-08 Thread Eddie James
Mask the IRQ status to only the bits that the driver checks. This
prevents excessive driver warnings when operating in slave mode
when additional bits are set that the driver doesn't handle.

Signed-off-by: Eddie James 
---
 drivers/i2c/busses/i2c-aspeed.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
index 31268074c422..2a388911038a 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -69,6 +69,7 @@
  * These share bit definitions, so use the same values for the enable &
  * status bits.
  */
+#define ASPEED_I2CD_INTR_ALL   0xf000
 #define ASPEED_I2CD_INTR_SDA_DL_TIMEOUTBIT(14)
 #define ASPEED_I2CD_INTR_BUS_RECOVER_DONE  BIT(13)
 #define ASPEED_I2CD_INTR_SLAVE_MATCH   BIT(7)
@@ -604,6 +605,7 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
writel(irq_received & ~ASPEED_I2CD_INTR_RX_DONE,
   bus->base + ASPEED_I2C_INTR_STS_REG);
readl(bus->base + ASPEED_I2C_INTR_STS_REG);
+   irq_received &= ASPEED_I2CD_INTR_ALL;
irq_remaining = irq_received;
 
 #if IS_ENABLED(CONFIG_I2C_SLAVE)
-- 
2.26.2



[PATCH v2 5/5] ARM: dts: Aspeed: Rainier: Add IBM Operation Panel I2C device

2020-09-08 Thread Eddie James
Set I2C bus 7 to multi-master mode and add the panel device that will
register as a slave.

Signed-off-by: Eddie James 
Reviewed-by: Joel Stanley 
---
 arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts 
b/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
index b94421f6cbd5..50d528444f5d 100644
--- a/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
@@ -4,6 +4,7 @@
 
 #include "aspeed-g6.dtsi"
 #include 
+#include 
 #include 
 
 / {
@@ -698,6 +699,7 @@ eeprom@53 {
 };
 
  {
+   multi-master;
status = "okay";
 
si7021-a20@20 {
@@ -831,6 +833,11 @@ gpio@15 {
};
};
 
+   ibm-panel@62 {
+   compatible = "ibm,op-panel";
+   reg = <(0x62 | I2C_OWN_SLAVE_ADDRESS)>;
+   };
+
dps: dps310@76 {
compatible = "infineon,dps310";
reg = <0x76>;
-- 
2.26.2



[PATCH v2 0/5] input: misc: Add IBM Operation Panel driver

2020-09-08 Thread Eddie James
This series adds support for input from the IBM Operation Panel, which is
a simple controller with three buttons and an LCD display meant for
interacting with a server. It's connected over I2C, typically to a service
processor. This series only supports the input from the panel, in which the
panel masters the I2C bus and sends data to the host system when someone
presses a button on the controller.

Changes since v1:
 - Redo DTS documentation example to use I2C_OWN_SLAVE_ADDRESS
 - Reject commands received in the input driver that are too long
 - Add a definition for the interrupt status mask in the Aspeed I2C driver
 - Use I2C_OWN_SLAVE_ADDRESS for both dts additions

Eddie James (5):
  dt-bindings: input: Add documentation for IBM Operation Panel
  input: misc: Add IBM Operation Panel driver
  i2c: aspeed: Mask IRQ status to relevant bits
  ARM: dts: Aspeed: Tacoma: Add IBM Operation Panel I2C device
  ARM: dts: Aspeed: Rainier: Add IBM Operation Panel I2C device

 .../bindings/input/ibm,op-panel.yaml  |  39 
 MAINTAINERS   |   7 +
 arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts  |   7 +
 arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts   |   7 +
 drivers/i2c/busses/i2c-aspeed.c   |   2 +
 drivers/input/misc/Kconfig|  18 ++
 drivers/input/misc/Makefile   |   1 +
 drivers/input/misc/ibm-panel.c| 192 ++
 8 files changed, 273 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/input/ibm,op-panel.yaml
 create mode 100644 drivers/input/misc/ibm-panel.c

-- 
2.26.2



[PATCH v2 4/5] ARM: dts: Aspeed: Tacoma: Add IBM Operation Panel I2C device

2020-09-08 Thread Eddie James
Set I2C bus 0 to multi-master mode and add the panel device that will
register as a slave.

Signed-off-by: Eddie James 
Reviewed-by: Joel Stanley 
---
 arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts 
b/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts
index 5f4ee67ac787..4d070d6ba09f 100644
--- a/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts
@@ -4,6 +4,7 @@
 
 #include "aspeed-g6.dtsi"
 #include 
+#include 
 #include 
 
 / {
@@ -438,7 +439,13 @@ aliases {
 };
 
  {
+   multi-master;
status = "okay";
+
+   ibm-panel@62 {
+   compatible = "ibm,op-panel";
+   reg = <(0x62 | I2C_OWN_SLAVE_ADDRESS)>;
+   };
 };
 
  {
-- 
2.26.2



[PATCH v2 1/5] dt-bindings: input: Add documentation for IBM Operation Panel

2020-09-08 Thread Eddie James
Document the bindings for the IBM Operation Panel, which provides
a simple interface to control a server. It has a display and three
buttons.
Also update MAINTAINERS for the new file.

Signed-off-by: Eddie James 
Acked-by: Joel Stanley 
---
 .../bindings/input/ibm,op-panel.yaml  | 39 +++
 MAINTAINERS   |  6 +++
 2 files changed, 45 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/input/ibm,op-panel.yaml

diff --git a/Documentation/devicetree/bindings/input/ibm,op-panel.yaml 
b/Documentation/devicetree/bindings/input/ibm,op-panel.yaml
new file mode 100644
index ..5f068fce93ad
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/ibm,op-panel.yaml
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/ibm,op-panel.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: IBM Operation Panel
+
+maintainers:
+  - Eddie James 
+
+description: |
+  The IBM Operation Panel provides a simple interface to control the connected
+  server. It has a display and three buttons: two directional arrows and one
+  'Enter' button.
+
+properties:
+  compatible:
+const: ibm,op-panel
+
+  reg:
+maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+examples:
+  - |
+#include 
+i2c {
+#address-cells = <1>;
+#size-cells = <0>;
+
+ibm-op-panel@62 {
+compatible = "ibm,op-panel";
+reg = <(0x62 | I2C_OWN_SLAVE_ADDRESS)>;
+};
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index 4a5d6797a206..0d83eada50e4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8345,6 +8345,12 @@ T:   git 
git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux.git
 F: Documentation/ia64/
 F: arch/ia64/
 
+IBM Operation Panel Input Driver
+M: Eddie James 
+L: linux-in...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/input/ibm,op-panel.yaml
+
 IBM Power 842 compression accelerator
 M: Haren Myneni 
 S: Supported
-- 
2.26.2



[PATCH v2 2/5] input: misc: Add IBM Operation Panel driver

2020-09-08 Thread Eddie James
Add a driver to get the button events from the panel and provide
them to userspace with the input subsystem. The panel is
connected with I2C and controls the bus, so the driver registers
as an I2C slave device.

Signed-off-by: Eddie James 
Reviewed-by: Joel Stanley 
---
 MAINTAINERS|   1 +
 drivers/input/misc/Kconfig |  18 
 drivers/input/misc/Makefile|   1 +
 drivers/input/misc/ibm-panel.c | 192 +
 4 files changed, 212 insertions(+)
 create mode 100644 drivers/input/misc/ibm-panel.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 0d83eada50e4..0f9605c4cfc6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8350,6 +8350,7 @@ M:Eddie James 
 L: linux-in...@vger.kernel.org
 S: Maintained
 F: Documentation/devicetree/bindings/input/ibm,op-panel.yaml
+F: drivers/input/misc/ibm-panel.c
 
 IBM Power 842 compression accelerator
 M: Haren Myneni 
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 362e8a01980c..65ab1ce7b259 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -708,6 +708,24 @@ config INPUT_ADXL34X_SPI
  To compile this driver as a module, choose M here: the
  module will be called adxl34x-spi.
 
+config INPUT_IBM_PANEL
+   tristate "IBM Operation Panel driver"
+   depends on I2C_SLAVE || COMPILE_TEST
+   help
+ Say Y here if you have an IBM Operation Panel connected to your system
+ over I2C. The panel is typically connected only to a system's service
+ processor (BMC).
+
+ If unsure, say N.
+
+ The Operation Panel is a controller with some buttons and an LCD
+ display that allows someone with physical access to the system to
+ perform various administrative tasks. This driver only supports the 
part
+ of the controller that sends commands to the system.
+
+ To compile this driver as a module, choose M here: the module will be
+ called ibm-panel.
+
 config INPUT_IMS_PCU
tristate "IMS Passenger Control Unit driver"
depends on USB
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index a48e5f2d859d..7e9edf0a142b 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_INPUT_GPIO_DECODER)  += gpio_decoder.o
 obj-$(CONFIG_INPUT_GPIO_VIBRA) += gpio-vibra.o
 obj-$(CONFIG_INPUT_HISI_POWERKEY)  += hisi_powerkey.o
 obj-$(CONFIG_HP_SDC_RTC)   += hp_sdc_rtc.o
+obj-$(CONFIG_INPUT_IBM_PANEL)  += ibm-panel.o
 obj-$(CONFIG_INPUT_IMS_PCU)+= ims-pcu.o
 obj-$(CONFIG_INPUT_IQS269A)+= iqs269a.o
 obj-$(CONFIG_INPUT_IXP4XX_BEEPER)  += ixp4xx-beeper.o
diff --git a/drivers/input/misc/ibm-panel.c b/drivers/input/misc/ibm-panel.c
new file mode 100644
index ..7b147b090c2a
--- /dev/null
+++ b/drivers/input/misc/ibm-panel.c
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) IBM Corporation 2020
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEVICE_NAME"ibm-panel"
+
+struct ibm_panel {
+   u8 idx;
+   u8 command[11];
+   spinlock_t lock;/* protects writes to idx and command */
+   struct input_dev *input;
+};
+
+static void ibm_panel_process_command(struct ibm_panel *panel, u8 command_size)
+{
+   u8 i;
+   u8 chksum;
+   u16 sum = 0;
+   int pressed;
+   int released;
+
+   if (command_size != sizeof(panel->command)) {
+   dev_dbg(>input->dev, "command size incorrect\n");
+   return;
+   }
+
+   if (panel->command[0] != 0xff && panel->command[1] != 0xf0) {
+   dev_dbg(>input->dev, "command invalid\n");
+   return;
+   }
+
+   for (i = 0; i < sizeof(panel->command) - 1; ++i) {
+   sum += panel->command[i];
+   if (sum & 0xff00) {
+   sum &= 0xff;
+   sum++;
+   }
+   }
+
+   chksum = sum & 0xff;
+   chksum = ~chksum;
+   chksum++;
+
+   if (chksum != panel->command[sizeof(panel->command) - 1]) {
+   dev_dbg(>input->dev, "command failed checksum\n");
+   return;
+   }
+
+   released = panel->command[2] & 0x80;
+   pressed = released ? 0 : 1;
+
+   switch (panel->command[2] & 0xf) {
+   case 0:
+   input_report_key(panel->input, BTN_NORTH, pressed);
+   break;
+   case 1:
+   input_report_key(panel->input, BTN_SOUTH, pressed);
+   break;
+   case 2:
+   input_report_key(panel->input, BTN_SELECT, pressed);
+   break;
+   default:
+   dev_dbg(>input

Re: [PATCH 2/5] input: misc: Add IBM Operation Panel driver

2020-09-02 Thread Eddie James



On 9/1/20 1:11 AM, Wolfram Sang wrote:

+   switch (event) {
+   case I2C_SLAVE_STOP:
+   command_size = panel->idx;
+   fallthrough;
+   case I2C_SLAVE_WRITE_REQUESTED:
+   panel->idx = 0;
+   break;
+   case I2C_SLAVE_WRITE_RECEIVED:
+   if (panel->idx < sizeof(panel->command))
+   panel->command[panel->idx++] = *val;
+   else
+   dev_dbg(>input->dev, "command truncated\n");

Just double checking: Do you really want to process truncated commands?
Since you detect the state here, you could also choose to reject such
commands?



Yes I suppose not. It could still be a valid command with extra bytes, 
but unlikely, so probably better not to handle it.



Thanks,

Eddie






Re: [PATCH 3/5] i2c: aspeed: Mask IRQ status to relevant bits

2020-08-25 Thread Eddie James



On 8/25/20 1:38 AM, Joel Stanley wrote:

On Thu, 20 Aug 2020 at 16:12, Eddie James  wrote:

Mask the IRQ status to only the bits that the driver checks. This
prevents excessive driver warnings when operating in slave mode
when additional bits are set that the driver doesn't handle.

Signed-off-by: Eddie James 
---
  drivers/i2c/busses/i2c-aspeed.c | 1 +
  1 file changed, 1 insertion(+)

diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
index 31268074c422..abf40f2af8b4 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -604,6 +604,7 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
 writel(irq_received & ~ASPEED_I2CD_INTR_RX_DONE,
bus->base + ASPEED_I2C_INTR_STS_REG);
 readl(bus->base + ASPEED_I2C_INTR_STS_REG);
+   irq_received &= 0xf000;
 irq_remaining = irq_received;

This would defeat the check for irq_remaining. I don't think we want to do this.

Can you explain why these bits are being set in slave mode?



No, I don't have any documentation for the bits that are masked off 
here, so I don't know why they would get set.


The check for irq_remaining is still useful for detecting that the 
driver state machine might be out of sync with what the master is doing.



Thanks,

Eddie




Re: [PATCH 4/7] dt-bindings: fsi: fsi2spi: Document new restricted property

2020-08-20 Thread Eddie James



On 8/20/20 12:14 PM, Mark Brown wrote:

On Thu, Aug 20, 2020 at 12:02:25PM -0500, Eddie James wrote:

Add documentation for the "fsi2spi,restricted" property which indicates
a controller shouldn't sequence loops and therefore has a smaller
transfer size.

In what situation might someone set this?  It sounds like a
configuration option rather than a description of the hardware.



It is a description of the configuration of the hardware. For 
controllers that are configured to be restricted for security purposes, 
this property will be set.


Thanks,

Eddie




Re: [PATCH 2/7] spi: fsi: Fix clock running too fast

2020-08-20 Thread Eddie James



On 8/20/20 12:12 PM, Mark Brown wrote:

On Thu, Aug 20, 2020 at 12:02:23PM -0500, Eddie James wrote:

From: Brad Bishop 

Use a clock divider tuned to a 200MHz FSI clock.  Use of the previous
divider at 200MHz results in corrupt data from endpoint devices. Ideally
the clock divider would be calculated from the FSI clock, but that
would require some significant work on the FSI driver.

Presumably this divider was chosen for FSI clocks that aren't 200MHz -
how will those be handled?



They aren't handled at the moment, but 200MHz FSI represents the worst 
case, as it's the maximum. Slower FSI clocks will simply result in 
slower SPI clocks.


Thanks,

Eddie




[PATCH 5/7] spi: fsi: Implement restricted size for certain controllers

2020-08-20 Thread Eddie James
Some of the FSI-attached SPI controllers cannot use the loop command in
programming the sequencer due to security requirements. Add a boolean
devicetree property that describes this condition and restrict the
size for these controllers. Also, add more transfers directly in the
sequence up to the length of the sequence register.

Fixes: bbb6b2f9865b ("spi: Add FSI-attached SPI controller driver")
Signed-off-by: Eddie James 
Reviewed-by: Joel Stanley 
Signed-off-by: Joel Stanley 
---
 drivers/spi/spi-fsi.c | 65 +++
 1 file changed, 53 insertions(+), 12 deletions(-)

diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c
index c31a852b6a3e..53cfa201e187 100644
--- a/drivers/spi/spi-fsi.c
+++ b/drivers/spi/spi-fsi.c
@@ -24,7 +24,8 @@
 
 #define SPI_FSI_BASE   0x7
 #define SPI_FSI_INIT_TIMEOUT_MS1000
-#define SPI_FSI_MAX_TRANSFER_SIZE  2048
+#define SPI_FSI_MAX_XFR_SIZE   2048
+#define SPI_FSI_MAX_XFR_SIZE_RESTRICTED32
 
 #define SPI_FSI_ERROR  0x0
 #define SPI_FSI_COUNTER_CFG0x1
@@ -74,6 +75,8 @@ struct fsi_spi {
struct device *dev; /* SPI controller device */
struct fsi_device *fsi; /* FSI2SPI CFAM engine device */
u32 base;
+   size_t max_xfr_size;
+   bool restricted;
 };
 
 struct fsi_spi_sequence {
@@ -209,8 +212,12 @@ static int fsi_spi_reset(struct fsi_spi *ctx)
if (rc)
return rc;
 
-   return fsi_spi_write_reg(ctx, SPI_FSI_CLOCK_CFG,
-SPI_FSI_CLOCK_CFG_RESET2);
+   rc = fsi_spi_write_reg(ctx, SPI_FSI_CLOCK_CFG,
+  SPI_FSI_CLOCK_CFG_RESET2);
+   if (rc)
+   return rc;
+
+   return fsi_spi_write_reg(ctx, SPI_FSI_STATUS, 0ULL);
 }
 
 static int fsi_spi_sequence_add(struct fsi_spi_sequence *seq, u8 val)
@@ -218,8 +225,8 @@ static int fsi_spi_sequence_add(struct fsi_spi_sequence 
*seq, u8 val)
/*
 * Add the next byte of instruction to the 8-byte sequence register.
 * Then decrement the counter so that the next instruction will go in
-* the right place. Return the number of "slots" left in the sequence
-* register.
+* the right place. Return the index of the slot we just filled in the
+* sequence register.
 */
seq->data |= (u64)val << seq->bit;
seq->bit -= 8;
@@ -237,9 +244,11 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
 struct fsi_spi_sequence *seq,
 struct spi_transfer *transfer)
 {
+   bool docfg = false;
int loops;
int idx;
int rc;
+   u8 val = 0;
u8 len = min(transfer->len, 8U);
u8 rem = transfer->len % len;
u64 cfg = 0ULL;
@@ -247,22 +256,42 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
loops = transfer->len / len;
 
if (transfer->tx_buf) {
-   idx = fsi_spi_sequence_add(seq,
-  SPI_FSI_SEQUENCE_SHIFT_OUT(len));
+   val = SPI_FSI_SEQUENCE_SHIFT_OUT(len);
+   idx = fsi_spi_sequence_add(seq, val);
+
if (rem)
rem = SPI_FSI_SEQUENCE_SHIFT_OUT(rem);
} else if (transfer->rx_buf) {
-   idx = fsi_spi_sequence_add(seq,
-  SPI_FSI_SEQUENCE_SHIFT_IN(len));
+   val = SPI_FSI_SEQUENCE_SHIFT_IN(len);
+   idx = fsi_spi_sequence_add(seq, val);
+
if (rem)
rem = SPI_FSI_SEQUENCE_SHIFT_IN(rem);
} else {
return -EINVAL;
}
 
+   if (ctx->restricted) {
+   const int eidx = rem ? 5 : 6;
+
+   while (loops > 1 && idx <= eidx) {
+   idx = fsi_spi_sequence_add(seq, val);
+   loops--;
+   docfg = true;
+   }
+
+   if (loops > 1) {
+   dev_warn(ctx->dev, "No sequencer slots; aborting.\n");
+   return -EINVAL;
+   }
+   }
+
if (loops > 1) {
fsi_spi_sequence_add(seq, SPI_FSI_SEQUENCE_BRANCH(idx));
+   docfg = true;
+   }
 
+   if (docfg) {
cfg = SPI_FSI_COUNTER_CFG_LOOPS(loops - 1);
if (transfer->rx_buf)
cfg |= SPI_FSI_COUNTER_CFG_N2_RX |
@@ -273,6 +302,8 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
rc = fsi_spi_write_reg(ctx, SPI_FSI_COUNTER_CFG, cfg);
if (rc)
return rc;
+   } else {
+   fsi_spi_write_reg(ctx, SPI_FSI_COUNTER_CFG, 0ULL);
}
 
if (rem)
@@ -429,7 +460,7 @@ static int fsi_spi_

[PATCH 2/7] spi: fsi: Fix clock running too fast

2020-08-20 Thread Eddie James
From: Brad Bishop 

Use a clock divider tuned to a 200MHz FSI clock.  Use of the previous
divider at 200MHz results in corrupt data from endpoint devices. Ideally
the clock divider would be calculated from the FSI clock, but that
would require some significant work on the FSI driver.

Signed-off-by: Brad Bishop 
Signed-off-by: Eddie James 
Signed-off-by: Joel Stanley 
---
 drivers/spi/spi-fsi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c
index 8f64af0140e0..559d0ff981f3 100644
--- a/drivers/spi/spi-fsi.c
+++ b/drivers/spi/spi-fsi.c
@@ -350,7 +350,7 @@ static int fsi_spi_transfer_init(struct fsi_spi *ctx)
u64 status = 0ULL;
u64 wanted_clock_cfg = SPI_FSI_CLOCK_CFG_ECC_DISABLE |
SPI_FSI_CLOCK_CFG_SCK_NO_DEL |
-   FIELD_PREP(SPI_FSI_CLOCK_CFG_SCK_DIV, 4);
+   FIELD_PREP(SPI_FSI_CLOCK_CFG_SCK_DIV, 19);
 
end = jiffies + msecs_to_jiffies(SPI_FSI_INIT_TIMEOUT_MS);
do {
-- 
2.26.2



[PATCH 0/7] spi: Fix FSI-attached controller and AT25 drivers

2020-08-20 Thread Eddie James
This series implements a number of fixes for the FSI-attached SPI controller
driver and the AT25 eeprom driver.

Brad Bishop (4):
  spi: fsi: Handle 9 to 15 byte transfers lengths
  spi: fsi: Fix clock running too fast
  spi: fsi: Fix use of the bneq+ sequencer instruction
  eeprom: at25: Split reads into chunks and cap write size

Eddie James (3):
  dt-bindings: fsi: fsi2spi: Document new restricted property
  spi: fsi: Implement restricted size for certain controllers
  spi: fsi: Check mux status before transfers

 .../devicetree/bindings/fsi/ibm,fsi2spi.yaml  |  10 ++
 drivers/misc/eeprom/at25.c|  94 +++-
 drivers/spi/spi-fsi.c | 139 ++
 3 files changed, 172 insertions(+), 71 deletions(-)

-- 
2.26.2



[PATCH 3/7] spi: fsi: Fix use of the bneq+ sequencer instruction

2020-08-20 Thread Eddie James
From: Brad Bishop 

All of the switches in N2_count_control in the counter configuration are
required to make the branch if not equal and increment command work.
Set them when using bneq+.

A side effect of this mode requires a dummy write to TDR when both
transmitting and receiving otherwise the controller won't start shifting
receive data.

It is likely not possible to avoid TDR underrun errors in this mode and
they are harmless, so do not check for them.

Fixes: bbb6b2f9865b ("spi: Add FSI-attached SPI controller driver")
Signed-off-by: Brad Bishop 
Signed-off-by: Eddie James 
Reviewed-by: Joel Stanley 
Signed-off-by: Joel Stanley 
---
 drivers/spi/spi-fsi.c | 28 +---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c
index 559d0ff981f3..c31a852b6a3e 100644
--- a/drivers/spi/spi-fsi.c
+++ b/drivers/spi/spi-fsi.c
@@ -29,6 +29,10 @@
 #define SPI_FSI_ERROR  0x0
 #define SPI_FSI_COUNTER_CFG0x1
 #define  SPI_FSI_COUNTER_CFG_LOOPS(x)   (((u64)(x) & 0xffULL) << 32)
+#define  SPI_FSI_COUNTER_CFG_N2_RX  BIT_ULL(8)
+#define  SPI_FSI_COUNTER_CFG_N2_TX  BIT_ULL(9)
+#define  SPI_FSI_COUNTER_CFG_N2_IMPLICIT BIT_ULL(10)
+#define  SPI_FSI_COUNTER_CFG_N2_RELOAD  BIT_ULL(11)
 #define SPI_FSI_CFG1   0x2
 #define SPI_FSI_CLOCK_CFG  0x3
 #define  SPI_FSI_CLOCK_CFG_MM_ENABLEBIT_ULL(32)
@@ -61,7 +65,7 @@
 #define  SPI_FSI_STATUS_RDR_OVERRUN BIT_ULL(62)
 #define  SPI_FSI_STATUS_RDR_FULLBIT_ULL(63)
 #define  SPI_FSI_STATUS_ANY_ERROR   \
-   (SPI_FSI_STATUS_ERROR | SPI_FSI_STATUS_TDR_UNDERRUN | \
+   (SPI_FSI_STATUS_ERROR | \
 SPI_FSI_STATUS_TDR_OVERRUN | SPI_FSI_STATUS_RDR_UNDERRUN | \
 SPI_FSI_STATUS_RDR_OVERRUN)
 #define SPI_FSI_PORT_CTRL  0x9
@@ -238,6 +242,7 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
int rc;
u8 len = min(transfer->len, 8U);
u8 rem = transfer->len % len;
+   u64 cfg = 0ULL;
 
loops = transfer->len / len;
 
@@ -258,8 +263,14 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
if (loops > 1) {
fsi_spi_sequence_add(seq, SPI_FSI_SEQUENCE_BRANCH(idx));
 
-   rc = fsi_spi_write_reg(ctx, SPI_FSI_COUNTER_CFG,
-  SPI_FSI_COUNTER_CFG_LOOPS(loops - 1));
+   cfg = SPI_FSI_COUNTER_CFG_LOOPS(loops - 1);
+   if (transfer->rx_buf)
+   cfg |= SPI_FSI_COUNTER_CFG_N2_RX |
+   SPI_FSI_COUNTER_CFG_N2_TX |
+   SPI_FSI_COUNTER_CFG_N2_IMPLICIT |
+   SPI_FSI_COUNTER_CFG_N2_RELOAD;
+
+   rc = fsi_spi_write_reg(ctx, SPI_FSI_COUNTER_CFG, cfg);
if (rc)
return rc;
}
@@ -275,6 +286,7 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx,
 {
int rc = 0;
u64 status = 0ULL;
+   u64 cfg = 0ULL;
 
if (transfer->tx_buf) {
int nb;
@@ -312,6 +324,16 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx,
u64 in = 0ULL;
u8 *rx = transfer->rx_buf;
 
+   rc = fsi_spi_read_reg(ctx, SPI_FSI_COUNTER_CFG, );
+   if (rc)
+   return rc;
+
+   if (cfg & SPI_FSI_COUNTER_CFG_N2_IMPLICIT) {
+   rc = fsi_spi_write_reg(ctx, SPI_FSI_DATA_TX, 0);
+   if (rc)
+   return rc;
+   }
+
while (transfer->len > recv) {
do {
rc = fsi_spi_read_reg(ctx, SPI_FSI_STATUS,
-- 
2.26.2



[PATCH 7/7] eeprom: at25: Split reads into chunks and cap write size

2020-08-20 Thread Eddie James
From: Brad Bishop 

Make use of spi_max_transfer_size to avoid requesting transfers that are
too large for some spi controllers.

Signed-off-by: Brad Bishop 
Signed-off-by: Eddie James 
Signed-off-by: Joel Stanley 
---
 drivers/misc/eeprom/at25.c | 94 ++
 1 file changed, 54 insertions(+), 40 deletions(-)

diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index ed8d38b09925..30f0704ab2d4 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -64,12 +64,17 @@ static int at25_ee_read(void *priv, unsigned int offset,
 {
struct at25_data *at25 = priv;
char *buf = val;
+   size_t max_chunk = spi_max_transfer_size(at25->spi);
+   size_t num_msgs = DIV_ROUND_UP(count, max_chunk);
+   size_t  nr_bytes = 0;
u8  command[EE_MAXADDRLEN + 1];
u8  *cp;
ssize_t status;
struct spi_transfer t[2];
struct spi_message  m;
u8  instr;
+   unsigned intmsg_offset;
+   size_t  msg_count;
 
if (unlikely(offset >= at25->chip.byte_len))
return -EINVAL;
@@ -78,57 +83,64 @@ static int at25_ee_read(void *priv, unsigned int offset,
if (unlikely(!count))
return -EINVAL;
 
-   cp = command;
-
-   instr = AT25_READ;
-   if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR)
-   if (offset >= (1U << (at25->addrlen * 8)))
-   instr |= AT25_INSTR_BIT3;
-   *cp++ = instr;
-
-   /* 8/16/24-bit address is written MSB first */
-   switch (at25->addrlen) {
-   default:/* case 3 */
-   *cp++ = offset >> 16;
-   fallthrough;
-   case 2:
-   *cp++ = offset >> 8;
-   fallthrough;
-   case 1:
-   case 0: /* can't happen: for better codegen */
-   *cp++ = offset >> 0;
-   }
+   msg_offset = (unsigned int)offset;
+   msg_count = min(count, max_chunk);
+   while (num_msgs) {
+   cp = command;
+
+   instr = AT25_READ;
+   if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR)
+   if (msg_offset >= (1U << (at25->addrlen * 8)))
+   instr |= AT25_INSTR_BIT3;
+   *cp++ = instr;
+
+   /* 8/16/24-bit address is written MSB first */
+   switch (at25->addrlen) {
+   default:/* case 3 */
+   *cp++ = msg_offset >> 16;
+   fallthrough;
+   case 2:
+   *cp++ = msg_offset >> 8;
+   fallthrough;
+   case 1:
+   case 0: /* can't happen: for better codegen */
+   *cp++ = msg_offset >> 0;
+   }
 
-   spi_message_init();
-   memset(t, 0, sizeof(t));
+   spi_message_init();
+   memset(t, 0, sizeof(t));
 
-   t[0].tx_buf = command;
-   t[0].len = at25->addrlen + 1;
-   spi_message_add_tail([0], );
+   t[0].tx_buf = command;
+   t[0].len = at25->addrlen + 1;
+   spi_message_add_tail([0], );
 
-   t[1].rx_buf = buf;
-   t[1].len = count;
-   spi_message_add_tail([1], );
+   t[1].rx_buf = buf + nr_bytes;
+   t[1].len = msg_count;
+   spi_message_add_tail([1], );
 
-   mutex_lock(>lock);
+   mutex_lock(>lock);
 
-   /* Read it all at once.
-*
-* REVISIT that's potentially a problem with large chips, if
-* other devices on the bus need to be accessed regularly or
-* this chip is clocked very slowly
-*/
-   status = spi_sync(at25->spi, );
-   dev_dbg(>spi->dev, "read %zu bytes at %d --> %zd\n",
-   count, offset, status);
+   status = spi_sync(at25->spi, );
 
-   mutex_unlock(>lock);
-   return status;
+   mutex_unlock(>lock);
+
+   if (status)
+   return status;
+
+   --num_msgs;
+   msg_offset += msg_count;
+   nr_bytes += msg_count;
+   }
+
+   dev_dbg(>spi->dev, "read %zu bytes at %d\n",
+   count, offset);
+   return 0;
 }
 
 static int at25_ee_write(void *priv, unsigned int off, void *val, size_t count)
 {
struct at25_data *at25 = priv;
+   size_t maxsz = spi_max_transfer_size(at25->spi);
const char *buf = val;
int status = 0;
unsignedbuf_size;
@@ -191,6 +203,8 @@ static int at25_ee_write(void *priv, unsigned int off, void 
*val, size_t count)
segm

[PATCH 6/7] spi: fsi: Check mux status before transfers

2020-08-20 Thread Eddie James
The SPI controllers are not accessible if the mux isn't set. Therefore,
check the mux status before starting a transfer and fail out if it isn't
set.

Signed-off-by: Eddie James 
Signed-off-by: Joel Stanley 
---
 drivers/spi/spi-fsi.c | 40 +++-
 1 file changed, 27 insertions(+), 13 deletions(-)

diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c
index 53cfa201e187..9c0a4413ec3d 100644
--- a/drivers/spi/spi-fsi.c
+++ b/drivers/spi/spi-fsi.c
@@ -12,6 +12,7 @@
 
 #define FSI_ENGID_SPI  0x23
 #define FSI_MBOX_ROOT_CTRL_8   0x2860
+#define  FSI_MBOX_ROOT_CTRL_8_SPI_MUX   0xf000
 
 #define FSI2SPI_DATA0  0x00
 #define FSI2SPI_DATA1  0x04
@@ -84,6 +85,26 @@ struct fsi_spi_sequence {
u64 data;
 };
 
+static int fsi_spi_check_mux(struct fsi_device *fsi, struct device *dev)
+{
+   int rc;
+   u32 root_ctrl_8;
+   __be32 root_ctrl_8_be;
+
+   rc = fsi_slave_read(fsi->slave, FSI_MBOX_ROOT_CTRL_8, _ctrl_8_be,
+   sizeof(root_ctrl_8_be));
+   if (rc)
+   return rc;
+
+   root_ctrl_8 = be32_to_cpu(root_ctrl_8_be);
+   dev_dbg(dev, "Root control register 8: %08x\n", root_ctrl_8);
+   if ((root_ctrl_8 & FSI_MBOX_ROOT_CTRL_8_SPI_MUX) ==
+FSI_MBOX_ROOT_CTRL_8_SPI_MUX)
+   return 0;
+
+   return -ENOLINK;
+}
+
 static int fsi_spi_check_status(struct fsi_spi *ctx)
 {
int rc;
@@ -449,11 +470,15 @@ static int fsi_spi_transfer_init(struct fsi_spi *ctx)
 static int fsi_spi_transfer_one_message(struct spi_controller *ctlr,
struct spi_message *mesg)
 {
-   int rc = 0;
+   int rc;
u8 seq_slave = SPI_FSI_SEQUENCE_SEL_SLAVE(mesg->spi->chip_select + 1);
struct spi_transfer *transfer;
struct fsi_spi *ctx = spi_controller_get_devdata(ctlr);
 
+   rc = fsi_spi_check_mux(ctx->fsi, ctx->dev);
+   if (rc)
+   return rc;
+
list_for_each_entry(transfer, >transfers, transfer_list) {
struct fsi_spi_sequence seq;
struct spi_transfer *next = NULL;
@@ -537,24 +562,13 @@ static size_t fsi_spi_max_transfer_size(struct spi_device 
*spi)
 static int fsi_spi_probe(struct device *dev)
 {
int rc;
-   u32 root_ctrl_8;
struct device_node *np;
int num_controllers_registered = 0;
struct fsi_device *fsi = to_fsi_dev(dev);
 
-   /*
-* Check the SPI mux before attempting to probe. If the mux isn't set
-* then the SPI controllers can't access their slave devices.
-*/
-   rc = fsi_slave_read(fsi->slave, FSI_MBOX_ROOT_CTRL_8, _ctrl_8,
-   sizeof(root_ctrl_8));
+   rc = fsi_spi_check_mux(fsi, dev);
if (rc)
-   return rc;
-
-   if (!root_ctrl_8) {
-   dev_dbg(dev, "SPI mux not set, aborting probe.\n");
return -ENODEV;
-   }
 
for_each_available_child_of_node(dev->of_node, np) {
u32 base;
-- 
2.26.2



[PATCH 4/7] dt-bindings: fsi: fsi2spi: Document new restricted property

2020-08-20 Thread Eddie James
Add documentation for the "fsi2spi,restricted" property which indicates
a controller shouldn't sequence loops and therefore has a smaller
transfer size.

Signed-off-by: Eddie James 
Acked-by: Joel Stanley 
Signed-off-by: Joel Stanley 
---
 Documentation/devicetree/bindings/fsi/ibm,fsi2spi.yaml | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/Documentation/devicetree/bindings/fsi/ibm,fsi2spi.yaml 
b/Documentation/devicetree/bindings/fsi/ibm,fsi2spi.yaml
index b26d4b4be743..0d2fb071fd00 100644
--- a/Documentation/devicetree/bindings/fsi/ibm,fsi2spi.yaml
+++ b/Documentation/devicetree/bindings/fsi/ibm,fsi2spi.yaml
@@ -24,6 +24,16 @@ properties:
 items:
   - description: FSI slave address
 
+patternProperties:
+  "^spi(@.*|-[0-9a-f])*$":
+type: object
+
+properties:
+  fsi2spi,restricted:
+description: indicates the controller should not use looping in the
+  sequencer and therefore has a smaller maximum transfer size
+type: boolean
+
 required:
   - compatible
   - reg
-- 
2.26.2



[PATCH 1/7] spi: fsi: Handle 9 to 15 byte transfers lengths

2020-08-20 Thread Eddie James
From: Brad Bishop 

The trailing  - 8 bytes of transfer data in this size range is no
longer ignored.

Fixes: bbb6b2f9865b ("spi: Add FSI-attached SPI controller driver")
Signed-off-by: Brad Bishop 
Signed-off-by: Eddie James 
Reviewed-by: Joel Stanley 
Signed-off-by: Joel Stanley 
---
 drivers/spi/spi-fsi.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c
index 37a3e0f8e752..8f64af0140e0 100644
--- a/drivers/spi/spi-fsi.c
+++ b/drivers/spi/spi-fsi.c
@@ -258,15 +258,15 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
if (loops > 1) {
fsi_spi_sequence_add(seq, SPI_FSI_SEQUENCE_BRANCH(idx));
 
-   if (rem)
-   fsi_spi_sequence_add(seq, rem);
-
rc = fsi_spi_write_reg(ctx, SPI_FSI_COUNTER_CFG,
   SPI_FSI_COUNTER_CFG_LOOPS(loops - 1));
if (rc)
return rc;
}
 
+   if (rem)
+   fsi_spi_sequence_add(seq, rem);
+
return 0;
 }
 
-- 
2.26.2



[PATCH 2/5] input: misc: Add IBM Operation Panel driver

2020-08-20 Thread Eddie James
Add a driver to get the button events from the panel and provide
them to userspace with the input subsystem. The panel is
connected with I2C and controls the bus, so the driver registers
as an I2C slave device.

Signed-off-by: Eddie James 
---
 MAINTAINERS|   1 +
 drivers/input/misc/Kconfig |  10 ++
 drivers/input/misc/Makefile|   1 +
 drivers/input/misc/ibm-panel.c | 186 +
 4 files changed, 198 insertions(+)
 create mode 100644 drivers/input/misc/ibm-panel.c

diff --git a/MAINTAINERS b/MAINTAINERS
index a9fd08e9cd54..077cc79ad7fd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8283,6 +8283,7 @@ M:Eddie James 
 L: linux-in...@vger.kernel.org
 S: Maintained
 F: Documentation/devicetree/bindings/input/ibm,op-panel.yaml
+F: drivers/input/misc/ibm-panel.c
 
 IBM Power 842 compression accelerator
 M: Haren Myneni 
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 362e8a01980c..88fb465a18b8 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -708,6 +708,16 @@ config INPUT_ADXL34X_SPI
  To compile this driver as a module, choose M here: the
  module will be called adxl34x-spi.
 
+config INPUT_IBM_PANEL
+   tristate "IBM Operation Panel driver"
+   depends on I2C_SLAVE || COMPILE_TEST
+   help
+ Supports the IBM Operation Panel as an input device. The panel is a
+ controller attached to the system with some buttons and an LCD display
+ that allows someone with physical access to the system to perform
+ various administrative tasks. This driver only supports the part of
+ the controller that sends commands to the system.
+
 config INPUT_IMS_PCU
tristate "IMS Passenger Control Unit driver"
depends on USB
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index a48e5f2d859d..7e9edf0a142b 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_INPUT_GPIO_DECODER)  += gpio_decoder.o
 obj-$(CONFIG_INPUT_GPIO_VIBRA) += gpio-vibra.o
 obj-$(CONFIG_INPUT_HISI_POWERKEY)  += hisi_powerkey.o
 obj-$(CONFIG_HP_SDC_RTC)   += hp_sdc_rtc.o
+obj-$(CONFIG_INPUT_IBM_PANEL)  += ibm-panel.o
 obj-$(CONFIG_INPUT_IMS_PCU)+= ims-pcu.o
 obj-$(CONFIG_INPUT_IQS269A)+= iqs269a.o
 obj-$(CONFIG_INPUT_IXP4XX_BEEPER)  += ixp4xx-beeper.o
diff --git a/drivers/input/misc/ibm-panel.c b/drivers/input/misc/ibm-panel.c
new file mode 100644
index ..607e7dd5a0fb
--- /dev/null
+++ b/drivers/input/misc/ibm-panel.c
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) IBM Corporation 2020
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEVICE_NAME"ibm-panel"
+
+struct ibm_panel {
+   u8 idx;
+   u8 command[11];
+   spinlock_t lock;/* protects writes to idx and command */
+   struct input_dev *input;
+};
+
+static void ibm_panel_process_command(struct ibm_panel *panel, u8 command_size)
+{
+   u8 i;
+   u8 chksum;
+   u16 sum = 0;
+   int pressed;
+   int released;
+
+   if (command_size != sizeof(panel->command)) {
+   dev_dbg(>input->dev, "command too short\n");
+   return;
+   }
+
+   if (panel->command[0] != 0xff && panel->command[1] != 0xf0) {
+   dev_dbg(>input->dev, "command invalid\n");
+   return;
+   }
+
+   for (i = 0; i < sizeof(panel->command) - 1; ++i) {
+   sum += panel->command[i];
+   if (sum & 0xff00) {
+   sum &= 0xff;
+   sum++;
+   }
+   }
+
+   chksum = sum & 0xff;
+   chksum = ~chksum;
+   chksum++;
+
+   if (chksum != panel->command[sizeof(panel->command) - 1]) {
+   dev_dbg(>input->dev, "command failed checksum\n");
+   return;
+   }
+
+   released = panel->command[2] & 0x80;
+   pressed = released ? 0 : 1;
+
+   switch (panel->command[2] & 0xf) {
+   case 0:
+   input_report_key(panel->input, BTN_NORTH, pressed);
+   break;
+   case 1:
+   input_report_key(panel->input, BTN_SOUTH, pressed);
+   break;
+   case 2:
+   input_report_key(panel->input, BTN_SELECT, pressed);
+   break;
+   default:
+   dev_dbg(>input->dev, "unknown command %u\n",
+   panel->command[2] & 0xf);
+   return;
+   }
+
+   input_sync(panel->input);
+}
+
+static int ibm_panel_i2c_slave_cb(struct i2c_client *client,
+ enum i2c_slave_event event

[PATCH 0/5] input: misc: Add IBM Operation Panel driver

2020-08-20 Thread Eddie James
This series adds support for input from the IBM Operation Panel, which is
a simple controller with three buttons and an LCD display meant for
interacting with a server. It's connected over I2C. This series only
supports the input from the panel, in which the panel masters the I2C bus
and sends data to the host system when someone presses a button on the
controller.

Eddie James (5):
  dt-bindings: input: Add documentation for IBM Operation Panel
  input: misc: Add IBM Operation Panel driver
  i2c: aspeed: Mask IRQ status to relevant bits
  ARM: dts: Aspeed: Tacoma: Add IBM Operation Panel I2C device
  ARM: dts: Aspeed: Rainier: Add IBM Operation Panel I2C device

 .../bindings/input/ibm,op-panel.yaml  |  38 
 MAINTAINERS   |   7 +
 arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts  |   6 +
 arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts   |   6 +
 drivers/i2c/busses/i2c-aspeed.c   |   1 +
 drivers/input/misc/Kconfig|  10 +
 drivers/input/misc/Makefile   |   1 +
 drivers/input/misc/ibm-panel.c| 186 ++
 8 files changed, 255 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/input/ibm,op-panel.yaml
 create mode 100644 drivers/input/misc/ibm-panel.c

-- 
2.26.2



[PATCH 1/5] dt-bindings: input: Add documentation for IBM Operation Panel

2020-08-20 Thread Eddie James
Document the bindings for the IBM Operation Panel, which provides
a simple interface to control a server. It has a display and three
buttons.
Also update MAINTAINERS for the new file.

Signed-off-by: Eddie James 
---
 .../bindings/input/ibm,op-panel.yaml  | 38 +++
 MAINTAINERS   |  6 +++
 2 files changed, 44 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/input/ibm,op-panel.yaml

diff --git a/Documentation/devicetree/bindings/input/ibm,op-panel.yaml 
b/Documentation/devicetree/bindings/input/ibm,op-panel.yaml
new file mode 100644
index ..86a32e8f3ef0
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/ibm,op-panel.yaml
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/ibm,op-panel.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: IBM Operation Panel
+
+maintainers:
+  - Eddie James 
+
+description: |
+  The IBM Operation Panel provides a simple interface to control the connected
+  server. It has a display and three buttons: two directional arrows and one
+  'Enter' button.
+
+properties:
+  compatible:
+const: ibm,op-panel
+
+  reg:
+maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+examples:
+  - |
+i2c {
+#address-cells = <1>;
+#size-cells = <0>;
+
+ibm-op-panel@62 {
+compatible = "ibm,op-panel";
+reg = <0x4062>; /* I2C_OWN_SLAVE_ADDRESS */
+};
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index ac79fdbdf8d0..a9fd08e9cd54 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8278,6 +8278,12 @@ T:   git 
git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux.git
 F: Documentation/ia64/
 F: arch/ia64/
 
+IBM Operation Panel Input Driver
+M: Eddie James 
+L: linux-in...@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/input/ibm,op-panel.yaml
+
 IBM Power 842 compression accelerator
 M: Haren Myneni 
 S: Supported
-- 
2.26.2



[PATCH 5/5] ARM: dts: Aspeed: Rainier: Add IBM Operation Panel I2C device

2020-08-20 Thread Eddie James
Set I2C bus 7 to multi-master mode and add the panel device that will
register as a slave.

Signed-off-by: Eddie James 
---
 arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts 
b/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
index b94421f6cbd5..f121f3c26a3a 100644
--- a/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
@@ -698,6 +698,7 @@ eeprom@53 {
 };
 
  {
+   multi-master;
status = "okay";
 
si7021-a20@20 {
@@ -831,6 +832,11 @@ gpio@15 {
};
};
 
+   ibm-panel@62 {
+   compatible = "ibm,op-panel";
+   reg = <0x4062>; /* I2C_OWN_SLAVE_ADDRESS */
+   };
+
dps: dps310@76 {
compatible = "infineon,dps310";
reg = <0x76>;
-- 
2.26.2



[PATCH 4/5] ARM: dts: Aspeed: Tacoma: Add IBM Operation Panel I2C device

2020-08-20 Thread Eddie James
Set I2C bus 0 to multi-master mode and add the panel device that will
register as a slave.

Signed-off-by: Eddie James 
---
 arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts 
b/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts
index 5f4ee67ac787..9cf2e02ae9e2 100644
--- a/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts
@@ -438,7 +438,13 @@ aliases {
 };
 
  {
+   multi-master;
status = "okay";
+
+   ibm-panel@62 {
+   compatible = "ibm,op-panel";
+   reg = <0x4062>; /* I2C_OWN_SLAVE_ADDRESS */
+   };
 };
 
  {
-- 
2.26.2



[PATCH 3/5] i2c: aspeed: Mask IRQ status to relevant bits

2020-08-20 Thread Eddie James
Mask the IRQ status to only the bits that the driver checks. This
prevents excessive driver warnings when operating in slave mode
when additional bits are set that the driver doesn't handle.

Signed-off-by: Eddie James 
---
 drivers/i2c/busses/i2c-aspeed.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
index 31268074c422..abf40f2af8b4 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -604,6 +604,7 @@ static irqreturn_t aspeed_i2c_bus_irq(int irq, void *dev_id)
writel(irq_received & ~ASPEED_I2CD_INTR_RX_DONE,
   bus->base + ASPEED_I2C_INTR_STS_REG);
readl(bus->base + ASPEED_I2C_INTR_STS_REG);
+   irq_received &= 0xf000;
irq_remaining = irq_received;
 
 #if IS_ENABLED(CONFIG_I2C_SLAVE)
-- 
2.26.2



[PATCH v2 1/2] dt-bindings: leds: pca955x: Add IBM implementation compatible string

2020-08-03 Thread Eddie James
IBM created an implementation of the PCA9552 on a PIC16F
microcontroller. Document the new compatible string for this device.

Signed-off-by: Eddie James 
---
 Documentation/devicetree/bindings/leds/leds-pca955x.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/leds/leds-pca955x.txt 
b/Documentation/devicetree/bindings/leds/leds-pca955x.txt
index 7a5830f8d5ab..817f460f3a72 100644
--- a/Documentation/devicetree/bindings/leds/leds-pca955x.txt
+++ b/Documentation/devicetree/bindings/leds/leds-pca955x.txt
@@ -9,6 +9,7 @@ Required properties:
"nxp,pca9550"
"nxp,pca9551"
"nxp,pca9552"
+   "ibm,pca9552"
"nxp,pca9553"
 - #address-cells: must be 1
 - #size-cells: must be 0
-- 
2.24.0



[PATCH v2 2/2] leds: pca955x: Add an IBM software implementation of the PCA9552 chip

2020-08-03 Thread Eddie James
IBM created an implementation of the PCA9552 on a PIC16F
microcontroller. The I2C device addresses are different from the
hardware PCA9552, so add a new compatible string and associated
platform data to be able to probe this device.

Signed-off-by: Eddie James 
Reviewed-by: Vishwanatha Subbanna 
---
 drivers/leds/leds-pca955x.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index 131f8e922ade..7087ca4592fc 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -65,6 +65,7 @@ enum pca955x_type {
pca9550,
pca9551,
pca9552,
+   ibm_pca9552,
pca9553,
 };
 
@@ -90,6 +91,11 @@ static struct pca955x_chipdef pca955x_chipdefs[] = {
.slv_addr   = /* 1100xxx */ 0x60,
.slv_addr_shift = 3,
},
+   [ibm_pca9552] = {
+   .bits   = 16,
+   .slv_addr   = /* 0110xxx */ 0x30,
+   .slv_addr_shift = 3,
+   },
[pca9553] = {
.bits   = 4,
.slv_addr   = /* 110001x */ 0x62,
@@ -101,6 +107,7 @@ static const struct i2c_device_id pca955x_id[] = {
{ "pca9550", pca9550 },
{ "pca9551", pca9551 },
{ "pca9552", pca9552 },
+   { "ibm-pca9552", ibm_pca9552 },
{ "pca9553", pca9553 },
{ }
 };
@@ -412,6 +419,7 @@ static const struct of_device_id of_pca955x_match[] = {
{ .compatible = "nxp,pca9550", .data = (void *)pca9550 },
{ .compatible = "nxp,pca9551", .data = (void *)pca9551 },
{ .compatible = "nxp,pca9552", .data = (void *)pca9552 },
+   { .compatible = "ibm,pca9552", .data = (void *)ibm_pca9552 },
{ .compatible = "nxp,pca9553", .data = (void *)pca9553 },
{},
 };
-- 
2.24.0



[PATCH v2 0/2] leds: pca955x: Add IBM software implemenation of the PCA9552 chip

2020-08-03 Thread Eddie James
IBM created an implementation of the PCA9552 on a PIC16F
microcontroller. The I2C device addresses are different from the
hardware PCA9552, so add a new compatible string and associated
platform data to be able to probe this device, and document the new
string.

Changes since v1:
 - Switch the vendor part of the compatible string to ibm
 - Change the enum in the driver to be ibm_

Eddie James (2):
  dt-bindings: leds: pca955x: Add IBM implementation compatible string
  leds: pca955x: Add an IBM software implementation of the PCA9552 chip

 Documentation/devicetree/bindings/leds/leds-pca955x.txt | 1 +
 drivers/leds/leds-pca955x.c | 8 
 2 files changed, 9 insertions(+)

-- 
2.24.0



Re: [PATCH 2/2] leds: pca955x: Add an IBM software implementation of the PCA9552 chip

2020-07-13 Thread Eddie James



On 7/9/20 3:50 PM, Andy Shevchenko wrote:

On Thu, Jul 9, 2020 at 11:16 PM Eddie James  wrote:

IBM created an implementation of the PCA9552 on a PIC16F
microcontroller. The I2C device addresses are different from the
hardware PCA9552, so add a new compatible string and associated
platform data to be able to probe this device.

This is weird. I would rather expect ibm prefix with corresponding part number.



Yep I agree now, see my note to Pavel just now.


Thanks,

Eddie





+   pca9552_ibm,
+   [pca9552_ibm] = {
+   { "pca9552-ibm", pca9552_ibm },
+   { .compatible = "nxp,pca9552-ibm", .data = (void *)pca9552_ibm },




Re: [PATCH 1/2] dt-bindings: leds: pca955x: Add IBM implementation compatible string

2020-07-13 Thread Eddie James



On 7/11/20 8:48 AM, Pavel Machek wrote:

Hi!


IBM created an implementation of the PCA9552 on a PIC16F
microcontroller. Document the new compatible string for this device.

Is the implementation opensource?



Hi, no it is not.





Signed-off-by: Eddie James 
+++ b/Documentation/devicetree/bindings/leds/leds-pca955x.txt
@@ -9,6 +9,7 @@ Required properties:
"nxp,pca9550"
"nxp,pca9551"
"nxp,pca9552"
+   "nxp,pca9552-ibm"
"nxp,pca9553"

Is it good idea to use nxp prefix for something that is
software-defined and not built by nxp?



Yea I suppose not...



Would ibm,pca9552 be better, or maybe even sw,pca9552 to indicate that
is not real hardware, but software emulation?



How about ibm,pca9552-sw? Someone suggested that just adding "sw" could 
be a problem if another company does the same thing but it isn't compatible.



Thanks for taking a look!

Eddie




Best regards,
Pavel


Re: [PATCH] fsi: fsi-occ: fix return value check in occ_probe()

2020-07-13 Thread Eddie James



On 7/12/20 10:33 PM, Xu Wang wrote:

In case of error, the function platform_device_register_full()
returns ERR_PTR() and never returns NULL. The NULL test in the
return value check should be replaced with IS_ERR().



Thanks,

Reviewed-by: Eddie James 




Signed-off-by: Xu Wang 
---
  drivers/fsi/fsi-occ.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/fsi/fsi-occ.c b/drivers/fsi/fsi-occ.c
index 7da9c81759ac..9eeb856c8905 100644
--- a/drivers/fsi/fsi-occ.c
+++ b/drivers/fsi/fsi-occ.c
@@ -555,7 +555,7 @@ static int occ_probe(struct platform_device *pdev)
  
  	hwmon_dev_info.id = occ->idx;

hwmon_dev = platform_device_register_full(_dev_info);
-   if (!hwmon_dev)
+   if (IS_ERR(hwmon_dev))
dev_warn(dev, "failed to create hwmon device\n");
  
  	return 0;


[PATCH 2/2] mmc: sdhci-of-aspeed: Fix clock divider calculation

2020-07-09 Thread Eddie James
When calculating the clock divider, start dividing at 2 instead of 1.
The divider is divided by two at the end of the calculation, so starting
at 1 may result in a divider of 0, which shouldn't happen.

Signed-off-by: Eddie James 
---
 drivers/mmc/host/sdhci-of-aspeed.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mmc/host/sdhci-of-aspeed.c 
b/drivers/mmc/host/sdhci-of-aspeed.c
index 56912e30c47e..a1bcc0f4ba9e 100644
--- a/drivers/mmc/host/sdhci-of-aspeed.c
+++ b/drivers/mmc/host/sdhci-of-aspeed.c
@@ -68,7 +68,7 @@ static void aspeed_sdhci_set_clock(struct sdhci_host *host, 
unsigned int clock)
if (WARN_ON(clock > host->max_clk))
clock = host->max_clk;
 
-   for (div = 1; div < 256; div *= 2) {
+   for (div = 2; div < 256; div *= 2) {
if ((parent / div) <= clock)
break;
}
-- 
2.24.0



[PATCH 1/2] clk: AST2600: Add mux for EMMC clock

2020-07-09 Thread Eddie James
The EMMC clock can be derived from either the HPLL or the MPLL. Register
a clock mux so that the rate is calculated correctly based upon the
parent.

Signed-off-by: Eddie James 
Reviewed-by: Andrew Jeffery 
---
 drivers/clk/clk-ast2600.c | 49 ---
 1 file changed, 41 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c
index 99afc949925f..177368cac6dd 100644
--- a/drivers/clk/clk-ast2600.c
+++ b/drivers/clk/clk-ast2600.c
@@ -131,6 +131,18 @@ static const struct clk_div_table ast2600_eclk_div_table[] 
= {
{ 0 }
 };
 
+static const struct clk_div_table ast2600_emmc_extclk_div_table[] = {
+   { 0x0, 2 },
+   { 0x1, 4 },
+   { 0x2, 6 },
+   { 0x3, 8 },
+   { 0x4, 10 },
+   { 0x5, 12 },
+   { 0x6, 14 },
+   { 0x7, 16 },
+   { 0 }
+};
+
 static const struct clk_div_table ast2600_mac_div_table[] = {
{ 0x0, 4 },
{ 0x1, 4 },
@@ -390,6 +402,11 @@ static struct clk_hw 
*aspeed_g6_clk_hw_register_gate(struct device *dev,
return hw;
 }
 
+static const char *const emmc_extclk_parent_names[] = {
+   "emmc_extclk_hpll_in",
+   "mpll",
+};
+
 static const char * const vclk_parent_names[] = {
"dpll",
"d1pll",
@@ -459,16 +476,32 @@ static int aspeed_g6_clk_probe(struct platform_device 
*pdev)
return PTR_ERR(hw);
aspeed_g6_clk_data->hws[ASPEED_CLK_UARTX] = hw;
 
-   /* EMMC ext clock divider */
-   hw = clk_hw_register_gate(dev, "emmc_extclk_gate", "hpll", 0,
-   scu_g6_base + ASPEED_G6_CLK_SELECTION1, 15, 0,
-   _g6_clk_lock);
+   /* EMMC ext clock */
+   hw = clk_hw_register_fixed_factor(dev, "emmc_extclk_hpll_in", "hpll",
+ 0, 1, 2);
if (IS_ERR(hw))
return PTR_ERR(hw);
-   hw = clk_hw_register_divider_table(dev, "emmc_extclk", 
"emmc_extclk_gate", 0,
-   scu_g6_base + ASPEED_G6_CLK_SELECTION1, 12, 3, 0,
-   ast2600_div_table,
-   _g6_clk_lock);
+
+   hw = clk_hw_register_mux(dev, "emmc_extclk_mux",
+emmc_extclk_parent_names,
+ARRAY_SIZE(emmc_extclk_parent_names), 0,
+scu_g6_base + ASPEED_G6_CLK_SELECTION1, 11, 1,
+0, _g6_clk_lock);
+   if (IS_ERR(hw))
+   return PTR_ERR(hw);
+
+   hw = clk_hw_register_gate(dev, "emmc_extclk_gate", "emmc_extclk_mux",
+ 0, scu_g6_base + ASPEED_G6_CLK_SELECTION1,
+ 15, 0, _g6_clk_lock);
+   if (IS_ERR(hw))
+   return PTR_ERR(hw);
+
+   hw = clk_hw_register_divider_table(dev, "emmc_extclk",
+  "emmc_extclk_gate", 0,
+  scu_g6_base +
+   ASPEED_G6_CLK_SELECTION1, 12,
+  3, 0, ast2600_emmc_extclk_div_table,
+  _g6_clk_lock);
if (IS_ERR(hw))
return PTR_ERR(hw);
aspeed_g6_clk_data->hws[ASPEED_CLK_EMMC] = hw;
-- 
2.24.0



[PATCH 0/2] clk: Aspeed: Fix eMMC clock speeds

2020-07-09 Thread Eddie James
There were two problems affecting clock speeds to the eMMC chip. Firstly, the
AST2600 clock was not muxed correctly to be derived from the MPLL. Secondly,
the SDHCI clock control divider was not calculated correctly. This series
addresses these problems.

Eddie James (2):
  clk: AST2600: Add mux for EMMC clock
  mmc: sdhci-of-aspeed: Fix clock divider calculation

 drivers/clk/clk-ast2600.c  | 49 +-
 drivers/mmc/host/sdhci-of-aspeed.c |  2 +-
 2 files changed, 42 insertions(+), 9 deletions(-)

-- 
2.24.0



[PATCH 2/2] leds: pca955x: Add an IBM software implementation of the PCA9552 chip

2020-07-09 Thread Eddie James
IBM created an implementation of the PCA9552 on a PIC16F
microcontroller. The I2C device addresses are different from the
hardware PCA9552, so add a new compatible string and associated
platform data to be able to probe this device.

Signed-off-by: Eddie James 
Reviewed-by: Vishwanatha Subbanna 
---
 drivers/leds/leds-pca955x.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index 4037c504589c..bf7ead45f66b 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -65,6 +65,7 @@ enum pca955x_type {
pca9550,
pca9551,
pca9552,
+   pca9552_ibm,
pca9553,
 };
 
@@ -90,6 +91,11 @@ static struct pca955x_chipdef pca955x_chipdefs[] = {
.slv_addr   = /* 1100xxx */ 0x60,
.slv_addr_shift = 3,
},
+   [pca9552_ibm] = {
+   .bits   = 16,
+   .slv_addr   = /* 0110xxx */ 0x30,
+   .slv_addr_shift = 3,
+   },
[pca9553] = {
.bits   = 4,
.slv_addr   = /* 110001x */ 0x62,
@@ -101,6 +107,7 @@ static const struct i2c_device_id pca955x_id[] = {
{ "pca9550", pca9550 },
{ "pca9551", pca9551 },
{ "pca9552", pca9552 },
+   { "pca9552-ibm", pca9552_ibm },
{ "pca9553", pca9553 },
{ }
 };
@@ -412,6 +419,7 @@ static const struct of_device_id of_pca955x_match[] = {
{ .compatible = "nxp,pca9550", .data = (void *)pca9550 },
{ .compatible = "nxp,pca9551", .data = (void *)pca9551 },
{ .compatible = "nxp,pca9552", .data = (void *)pca9552 },
+   { .compatible = "nxp,pca9552-ibm", .data = (void *)pca9552_ibm },
{ .compatible = "nxp,pca9553", .data = (void *)pca9553 },
{},
 };
-- 
2.24.0



[PATCH 1/2] dt-bindings: leds: pca955x: Add IBM implementation compatible string

2020-07-09 Thread Eddie James
IBM created an implementation of the PCA9552 on a PIC16F
microcontroller. Document the new compatible string for this device.

Signed-off-by: Eddie James 
---
 Documentation/devicetree/bindings/leds/leds-pca955x.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/leds/leds-pca955x.txt 
b/Documentation/devicetree/bindings/leds/leds-pca955x.txt
index 7a5830f8d5ab..28edb976ee77 100644
--- a/Documentation/devicetree/bindings/leds/leds-pca955x.txt
+++ b/Documentation/devicetree/bindings/leds/leds-pca955x.txt
@@ -9,6 +9,7 @@ Required properties:
"nxp,pca9550"
"nxp,pca9551"
"nxp,pca9552"
+   "nxp,pca9552-ibm"
"nxp,pca9553"
 - #address-cells: must be 1
 - #size-cells: must be 0
-- 
2.24.0



[PATCH 0/2] leds: pca955x: Add IBM software implemenation of the PCA9552 chip

2020-07-09 Thread Eddie James
IBM created an implementation of the PCA9552 on a PIC16F
microcontroller. The I2C device addresses are different from the
hardware PCA9552, so add a new compatible string and associated
platform data to be able to probe this device, and document the new
string.

Eddie James (2):
  dt-bindings: leds: pca955x: Add IBM implementation compatible string
  leds: pca955x: Add an IBM software implementation of the PCA9552 chip

 Documentation/devicetree/bindings/leds/leds-pca955x.txt | 1 +
 drivers/leds/leds-pca955x.c | 8 
 2 files changed, 9 insertions(+)

-- 
2.24.0



[PATCH] fsi: aspeed: Enable 23-bit addressing

2020-07-09 Thread Eddie James
In order to access more than the second hub link, 23-bit addressing is
required. The core provides the highest two bits of address as the slave
ID to the master.

OpenBMC-Staging-Count: 1
Signed-off-by: Eddie James 
Acked-by: Jeremy Kerr 
Signed-off-by: Joel Stanley 
---
 drivers/fsi/fsi-master-aspeed.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/fsi/fsi-master-aspeed.c b/drivers/fsi/fsi-master-aspeed.c
index f49742b310c2..b49dccf14315 100644
--- a/drivers/fsi/fsi-master-aspeed.c
+++ b/drivers/fsi/fsi-master-aspeed.c
@@ -241,9 +241,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 +274,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) {
-- 
2.24.0



Re: [PATCH v2 2/2] i2c: fsi: Prevent adding adapters for ports without dts nodes

2020-07-06 Thread Eddie James



On 7/4/20 1:39 AM, Wolfram Sang wrote:

On Tue, Jun 09, 2020 at 03:15:55PM -0500, Eddie James wrote:

Ports should be defined in the devicetree if they are to be enabled on
the system.

The patch description does not really fit anymore, does it? There is no
change in behaviour, we just remove a redundant check.



Hi, it does change the behavior actually. By checking for the device 
node pointer, it would proceed and create the port for a NULL device 
node, which is not the desired behavior.



Thanks,

Eddie





Signed-off-by: Eddie James 
Signed-off-by: Joel Stanley 
---
Changes since v1:
  - Remove the check for null device node since that is checked in
of_device_is_available

  drivers/i2c/busses/i2c-fsi.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-fsi.c b/drivers/i2c/busses/i2c-fsi.c
index 977d6f524649..10332693edf0 100644
--- a/drivers/i2c/busses/i2c-fsi.c
+++ b/drivers/i2c/busses/i2c-fsi.c
@@ -703,7 +703,7 @@ static int fsi_i2c_probe(struct device *dev)
  
  	for (port_no = 0; port_no < ports; port_no++) {

np = fsi_i2c_find_port_of_node(dev->of_node, port_no);
-   if (np && !of_device_is_available(np))
+   if (!of_device_is_available(np))
continue;
  
  		port = kzalloc(sizeof(*port), GFP_KERNEL);

--
2.24.0



[PATCH v2 2/2] i2c: fsi: Prevent adding adapters for ports without dts nodes

2020-06-09 Thread Eddie James
Ports should be defined in the devicetree if they are to be enabled on
the system.

Signed-off-by: Eddie James 
Signed-off-by: Joel Stanley 
---
Changes since v1:
 - Remove the check for null device node since that is checked in
   of_device_is_available

 drivers/i2c/busses/i2c-fsi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-fsi.c b/drivers/i2c/busses/i2c-fsi.c
index 977d6f524649..10332693edf0 100644
--- a/drivers/i2c/busses/i2c-fsi.c
+++ b/drivers/i2c/busses/i2c-fsi.c
@@ -703,7 +703,7 @@ static int fsi_i2c_probe(struct device *dev)
 
for (port_no = 0; port_no < ports; port_no++) {
np = fsi_i2c_find_port_of_node(dev->of_node, port_no);
-   if (np && !of_device_is_available(np))
+   if (!of_device_is_available(np))
continue;
 
port = kzalloc(sizeof(*port), GFP_KERNEL);
-- 
2.24.0



[PATCH v2 0/2] i2c: fsi: Fixes for systems with more ports

2020-06-09 Thread Eddie James
This series fixes a register definition for the FSI-attached I2C master to
allow all the available ports. In addition, the code to add an adapter for
each port is modified to require a device-tree entry for the bus. This is so
that systems with lots of busses that have no devices on them don't add lots
of unecessary devices.

Changes since v1:
 - Remove the check for null device node since that is checked in
   of_device_is_available

Eddie James (2):
  i2c: fsi: Fix the port number field in status register
  i2c: fsi: Prevent adding adapters for ports without dts nodes

 drivers/i2c/busses/i2c-fsi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

-- 
2.24.0



[PATCH v2 1/2] i2c: fsi: Fix the port number field in status register

2020-06-09 Thread Eddie James
The port number field in the status register was not correct, so fix it.

Fixes: d6ffb6300116 ("i2c: Add FSI-attached I2C master algorithm")
Signed-off-by: Eddie James 
Signed-off-by: Joel Stanley 
---
 drivers/i2c/busses/i2c-fsi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-fsi.c b/drivers/i2c/busses/i2c-fsi.c
index e0c256922d4f..977d6f524649 100644
--- a/drivers/i2c/busses/i2c-fsi.c
+++ b/drivers/i2c/busses/i2c-fsi.c
@@ -98,7 +98,7 @@
 #define I2C_STAT_DAT_REQ   BIT(25)
 #define I2C_STAT_CMD_COMP  BIT(24)
 #define I2C_STAT_STOP_ERR  BIT(23)
-#define I2C_STAT_MAX_PORT  GENMASK(19, 16)
+#define I2C_STAT_MAX_PORT  GENMASK(22, 16)
 #define I2C_STAT_ANY_INT   BIT(15)
 #define I2C_STAT_SCL_INBIT(11)
 #define I2C_STAT_SDA_INBIT(10)
-- 
2.24.0



Re: [PATCH 2/2] i2c: fsi: Prevent adding adapters for ports without dts nodes

2020-06-08 Thread Eddie James



On 6/8/20 11:31 AM, Andy Shevchenko wrote:

On Mon, Jun 8, 2020 at 7:05 PM Eddie James  wrote:

Ports should be defined in the devicetree if they are to be enabled on
the system.

...


 for (port_no = 0; port_no < ports; port_no++) {
 np = fsi_i2c_find_port_of_node(dev->of_node, port_no);
-   if (np && !of_device_is_available(np))
+   /* Do not add port if it is not described in the device tree */
+   if (!np)
+   continue;

I believe this is redundant, since below will do the same second time.



Good point, thanks, I'll update that.





+   /* Do not add port if it is described as disabled */
+   if (!of_device_is_available(np))
 continue;


[PATCH 2/2] i2c: fsi: Prevent adding adapters for ports without dts nodes

2020-06-08 Thread Eddie James
Ports should be defined in the devicetree if they are to be enabled on
the system.

Signed-off-by: Eddie James 
Signed-off-by: Joel Stanley 
---
 drivers/i2c/busses/i2c-fsi.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-fsi.c b/drivers/i2c/busses/i2c-fsi.c
index 977d6f524649..95b6b6bc1d78 100644
--- a/drivers/i2c/busses/i2c-fsi.c
+++ b/drivers/i2c/busses/i2c-fsi.c
@@ -703,7 +703,12 @@ static int fsi_i2c_probe(struct device *dev)
 
for (port_no = 0; port_no < ports; port_no++) {
np = fsi_i2c_find_port_of_node(dev->of_node, port_no);
-   if (np && !of_device_is_available(np))
+   /* Do not add port if it is not described in the device tree */
+   if (!np)
+   continue;
+
+   /* Do not add port if it is described as disabled */
+   if (!of_device_is_available(np))
continue;
 
port = kzalloc(sizeof(*port), GFP_KERNEL);
-- 
2.24.0



[PATCH 0/2] i2c: fsi: Fixes for systems with more ports

2020-06-08 Thread Eddie James
This series fixes a register definition for the FSI-attached I2C master to
allow all the available ports. In addition, the code to add an adapter for
each port is modified to require a device-tree entry for the bus. This is so
that systems with lots of busses that have no devices on them don't add lots
of unecessary devices.

Eddie James (2):
  i2c: fsi: Fix the port number field in status register
  i2c: fsi: Prevent adding adapters for ports without dts nodes

 drivers/i2c/busses/i2c-fsi.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

-- 
2.24.0



[PATCH 1/2] i2c: fsi: Fix the port number field in status register

2020-06-08 Thread Eddie James
The port number field in the status register was not correct, so fix it.

Fixes: d6ffb6300116 ("i2c: Add FSI-attached I2C master algorithm")
Signed-off-by: Eddie James 
Signed-off-by: Joel Stanley 
---
 drivers/i2c/busses/i2c-fsi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-fsi.c b/drivers/i2c/busses/i2c-fsi.c
index e0c256922d4f..977d6f524649 100644
--- a/drivers/i2c/busses/i2c-fsi.c
+++ b/drivers/i2c/busses/i2c-fsi.c
@@ -98,7 +98,7 @@
 #define I2C_STAT_DAT_REQ   BIT(25)
 #define I2C_STAT_CMD_COMP  BIT(24)
 #define I2C_STAT_STOP_ERR  BIT(23)
-#define I2C_STAT_MAX_PORT  GENMASK(19, 16)
+#define I2C_STAT_MAX_PORT  GENMASK(22, 16)
 #define I2C_STAT_ANY_INT   BIT(15)
 #define I2C_STAT_SCL_INBIT(11)
 #define I2C_STAT_SDA_INBIT(10)
-- 
2.24.0



Re: [PATCH 3/3] hwmon: (occ) Add new temperature sensor type

2020-05-06 Thread Eddie James



On 5/6/20 10:57 AM, Guenter Roeck wrote:

On Fri, May 01, 2020 at 10:08:33AM -0500, Eddie James wrote:

The latest version of the On-Chip Controller (OCC) has a different
format for the temperature sensor data. Add a new temperature sensor
version to handle this data.

Signed-off-by: Eddie James 

For my reference:

Acked-by: Guenter Roeck 

I assume this depends on at least patch 2 of the series, so we'll have
to wait for that to be accepted.



Thanks Guenter. Yes that's correct.

Eddie




Guenter


---
  drivers/hwmon/occ/common.c | 75 ++
  1 file changed, 75 insertions(+)

diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c
index 30e18eb60da7..52af0e728232 100644
--- a/drivers/hwmon/occ/common.c
+++ b/drivers/hwmon/occ/common.c
@@ -41,6 +41,14 @@ struct temp_sensor_2 {
u8 value;
  } __packed;
  
+struct temp_sensor_10 {

+   u32 sensor_id;
+   u8 fru_type;
+   u8 value;
+   u8 throttle;
+   u8 reserved;
+} __packed;
+
  struct freq_sensor_1 {
u16 sensor_id;
u16 value;
@@ -307,6 +315,60 @@ static ssize_t occ_show_temp_2(struct device *dev,
return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
  }
  
+static ssize_t occ_show_temp_10(struct device *dev,

+   struct device_attribute *attr, char *buf)
+{
+   int rc;
+   u32 val = 0;
+   struct temp_sensor_10 *temp;
+   struct occ *occ = dev_get_drvdata(dev);
+   struct occ_sensors *sensors = >sensors;
+   struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+   rc = occ_update_response(occ);
+   if (rc)
+   return rc;
+
+   temp = ((struct temp_sensor_10 *)sensors->temp.data) + sattr->index;
+
+   switch (sattr->nr) {
+   case 0:
+   val = get_unaligned_be32(>sensor_id);
+   break;
+   case 1:
+   val = temp->value;
+   if (val == OCC_TEMP_SENSOR_FAULT)
+   return -EREMOTEIO;
+
+   /*
+* VRM doesn't return temperature, only alarm bit. This
+* attribute maps to tempX_alarm instead of tempX_input for
+* VRM
+*/
+   if (temp->fru_type != OCC_FRU_TYPE_VRM) {
+   /* sensor not ready */
+   if (val == 0)
+   return -EAGAIN;
+
+   val *= 1000;
+   }
+   break;
+   case 2:
+   val = temp->fru_type;
+   break;
+   case 3:
+   val = temp->value == OCC_TEMP_SENSOR_FAULT;
+   break;
+   case 4:
+   val = temp->throttle * 1000;
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
+}
+
  static ssize_t occ_show_freq_1(struct device *dev,
   struct device_attribute *attr, char *buf)
  {
@@ -745,6 +807,10 @@ static int occ_setup_sensor_attrs(struct occ *occ)
num_attrs += (sensors->temp.num_sensors * 4);
show_temp = occ_show_temp_2;
break;
+   case 0x10:
+   num_attrs += (sensors->temp.num_sensors * 5);
+   show_temp = occ_show_temp_10;
+   break;
default:
sensors->temp.num_sensors = 0;
}
@@ -844,6 +910,15 @@ static int occ_setup_sensor_attrs(struct occ *occ)
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
 show_temp, NULL, 3, i);
attr++;
+
+   if (sensors->temp.version == 0x10) {
+   snprintf(attr->name, sizeof(attr->name),
+"temp%d_max", s);
+   attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+show_temp, NULL,
+4, i);
+   attr++;
+   }
}
}
  


[PATCH v11 4/8] soc: aspeed: xdma: Add reset ioctl

2020-05-05 Thread Eddie James
Users of the XDMA engine need a way to reset it if something goes wrong.
Problems on the host side, or user error, such as incorrect host
address, may result in the DMA operation never completing and no way to
determine what went wrong. Therefore, add an ioctl to reset the engine
so that users can recover in this situation.

Signed-off-by: Eddie James 
Acked-by: Andrew Jeffery 
---
 drivers/soc/aspeed/aspeed-xdma.c | 32 
 include/uapi/linux/aspeed-xdma.h |  4 
 2 files changed, 36 insertions(+)

diff --git a/drivers/soc/aspeed/aspeed-xdma.c b/drivers/soc/aspeed/aspeed-xdma.c
index b4d4d34..4d8af9e 100644
--- a/drivers/soc/aspeed/aspeed-xdma.c
+++ b/drivers/soc/aspeed/aspeed-xdma.c
@@ -638,6 +638,37 @@ static __poll_t aspeed_xdma_poll(struct file *file,
return mask;
 }
 
+static long aspeed_xdma_ioctl(struct file *file, unsigned int cmd,
+ unsigned long param)
+{
+   unsigned long flags;
+   struct aspeed_xdma_client *client = file->private_data;
+   struct aspeed_xdma *ctx = client->ctx;
+
+   switch (cmd) {
+   case ASPEED_XDMA_IOCTL_RESET:
+   spin_lock_irqsave(>engine_lock, flags);
+   if (ctx->in_reset) {
+   spin_unlock_irqrestore(>engine_lock, flags);
+   return 0;
+   }
+
+   ctx->in_reset = true;
+   spin_unlock_irqrestore(>engine_lock, flags);
+
+   if (READ_ONCE(ctx->current_client))
+   dev_warn(ctx->dev,
+"User reset with transfer in progress.\n");
+
+   aspeed_xdma_reset(ctx);
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
 static void aspeed_xdma_vma_close(struct vm_area_struct *vma)
 {
int rc;
@@ -756,6 +787,7 @@ static int aspeed_xdma_release(struct inode *inode, struct 
file *file)
.owner  = THIS_MODULE,
.write  = aspeed_xdma_write,
.poll   = aspeed_xdma_poll,
+   .unlocked_ioctl = aspeed_xdma_ioctl,
.mmap   = aspeed_xdma_mmap,
.open   = aspeed_xdma_open,
.release= aspeed_xdma_release,
diff --git a/include/uapi/linux/aspeed-xdma.h b/include/uapi/linux/aspeed-xdma.h
index 2efaa60..3a3646f 100644
--- a/include/uapi/linux/aspeed-xdma.h
+++ b/include/uapi/linux/aspeed-xdma.h
@@ -4,8 +4,12 @@
 #ifndef _UAPI_LINUX_ASPEED_XDMA_H_
 #define _UAPI_LINUX_ASPEED_XDMA_H_
 
+#include 
 #include 
 
+#define __ASPEED_XDMA_IOCTL_MAGIC  0xb7
+#define ASPEED_XDMA_IOCTL_RESET_IO(__ASPEED_XDMA_IOCTL_MAGIC, 
0)
+
 /*
  * aspeed_xdma_direction
  *
-- 
1.8.3.1



[PATCH v11 0/8] soc: aspeed: Add XDMA engine driver

2020-05-05 Thread Eddie James
This series adds a driver to control the Aspeed XDMA engine embedded in the
AST2500 and AST2600. The XDMA engine performs automatic DMA operations
over PCI-E between the Aspeed SOC (acting as a BMC) and a host processor.

Changes since v10:
 - Fix devicetree binding documentation
 - Add patches to enable the device on witherspoon and tacoma systems
 - Fix the driver to actually use the updated bindings
 - Remove the device managed memory in favor of manually allocating and freeing
   This adds considerable complexity to the probe function and requires the
   use of a kobject and associated release method, but it fixes the problem of
   the device context being deleted during an operation or with memory still
   mapped if the device is unbound from the driver
 - Remove the client kref system
 - Reset the device when a user closes a file handle with an on-going operation

Changes since v9:
 - Remove the kernel command queue
 - Use memcpy_toio instead to copy commands to the buffer
 - Free the client's genalloc'd memory in the release method
 - Switch the bindings documentation to yaml
 - Add patches to fix SCU interrupt controller include

Changes since v8:
 - Use DMA API to allocate memory from reserved region.
 - Fix the driver for the AST2500 by keeping the command queue in kernel
   memory and copying the whole buffer to the reserved memory area before
   starting the operation.
 - Add krefs to the client structure to prevent use-after-free.
 - Switch reset-names binding to "device", "root-complex"

Eddie James (8):
  dt-bindings: soc: Add Aspeed XDMA Engine
  soc: aspeed: Add XDMA Engine Driver
  soc: aspeed: xdma: Add user interface
  soc: aspeed: xdma: Add reset ioctl
  ARM: dts: Aspeed: AST2600: Update XDMA engine node
  ARM: dts: Aspeed: AST2500: Update XDMA engine node
  ARM: dts: Aspeed: Witherspoon: Enable XDMA engine
  ARM: dts: Aspeed: Tacoma: Enable XDMA engine

 .../devicetree/bindings/soc/aspeed/xdma.yaml   |  103 ++
 MAINTAINERS|8 +
 arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts|   11 +
 arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts   |   11 +
 arch/arm/boot/dts/aspeed-g5.dtsi   |5 +-
 arch/arm/boot/dts/aspeed-g6.dtsi   |8 +-
 drivers/soc/aspeed/Kconfig |8 +
 drivers/soc/aspeed/Makefile|1 +
 drivers/soc/aspeed/aspeed-xdma.c   | 1205 
 include/uapi/linux/aspeed-xdma.h   |   42 +
 10 files changed, 1397 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/soc/aspeed/xdma.yaml
 create mode 100644 drivers/soc/aspeed/aspeed-xdma.c
 create mode 100644 include/uapi/linux/aspeed-xdma.h

-- 
1.8.3.1



[PATCH v11 1/8] dt-bindings: soc: Add Aspeed XDMA Engine

2020-05-05 Thread Eddie James
Document the bindings for the Aspeed AST25XX and AST26XX XDMA engine.

Signed-off-by: Eddie James 
Reviewed-by: Andrew Jeffery 
---
 .../devicetree/bindings/soc/aspeed/xdma.yaml   | 103 +
 MAINTAINERS|   6 ++
 2 files changed, 109 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/soc/aspeed/xdma.yaml

diff --git a/Documentation/devicetree/bindings/soc/aspeed/xdma.yaml 
b/Documentation/devicetree/bindings/soc/aspeed/xdma.yaml
new file mode 100644
index 000..4957435
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/aspeed/xdma.yaml
@@ -0,0 +1,103 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/aspeed/xdma.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Aspeed AST25XX and AST26XX XDMA Engine
+
+maintainers:
+ - Eddie James 
+
+description: |
+  This binding describes the XDMA Engine embedded in the AST2500 and AST2600
+  SOCs. The XDMA engine can perform automatic DMA operations over PCI between
+  the SOC (acting as a BMC) and a host processor.
+
+properties:
+  compatible:
+enum:
+  - aspeed,ast2500-xdma
+  - aspeed,ast2600-xdma
+
+  reg:
+maxItems: 1
+
+  clocks:
+maxItems: 1
+
+  resets:
+minItems: 1
+maxItems: 2
+
+  reset-names:
+maxItems: 2
+items:
+  - const: device
+  - const: root-complex
+
+  interrupts:
+maxItems: 2
+items:
+  - description: global interrupt for the XDMA engine
+  - description: PCI-E reset or PERST interrupt
+
+  aspeed,scu:
+description: a reference to the System Control Unit node of the Aspeed SOC.
+allOf:
+  - $ref: /schemas/types.yaml#/definitions/phandle
+
+  aspeed,pcie-device:
+description: describes which PCI-E device the XDMA engine should use
+allOf:
+  - $ref: /schemas/types.yaml#/definitions/string
+  - enum: [ bmc, vga ]
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - resets
+  - interrupts-extended
+  - aspeed,scu
+  - memory-region
+
+if:
+  properties:
+compatible:
+  contains:
+const: aspeed,ast2600-xdma
+then:
+  required:
+- reset-names
+
+examples:
+  - |
+#include 
+#include 
+#include 
+syscon: syscon@1e6e2000 {
+reg = <0x1e6e2000 0x1000>;
+ranges = <0 0x1e6e2000 0x1000>;
+#address-cells = <1>;
+#size-cells = <1>;
+#clock-cells = <1>;
+#reset-cells = <1>;
+scu_ic0: interrupt-controller@560 {
+reg = <0x560 0x4>;
+interrupt-controller;
+#interrupt-cells = <1>;
+};
+};
+xdma@1e6e7000 {
+compatible = "aspeed,ast2600-xdma";
+reg = <0x1e6e7000 0x100>;
+clocks = < ASPEED_CLK_GATE_BCLK>;
+resets = < ASPEED_RESET_DEV_XDMA>, < 
ASPEED_RESET_RC_XDMA>;
+reset-names = "device", "root-complex";
+interrupts-extended = < GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+  <_ic0 
ASPEED_AST2600_SCU_IC0_PCIE_PERST_LO_TO_HI>;
+aspeed,scu = <>;
+aspeed,pcie-device = "bmc";
+memory-region = <_memory>;
+};
diff --git a/MAINTAINERS b/MAINTAINERS
index b103ff0..6a421fd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2780,6 +2780,12 @@ S:   Maintained
 F: Documentation/devicetree/bindings/media/aspeed-video.txt
 F: drivers/media/platform/aspeed-video.c
 
+ASPEED XDMA ENGINE DRIVER
+M: Eddie James 
+L: linux-asp...@lists.ozlabs.org (moderated for non-subscribers)
+S: Maintained
+F: Documentation/devicetree/bindings/soc/aspeed/xdma.yaml
+
 ASUS NOTEBOOKS AND EEEPC ACPI/WMI EXTRAS DRIVERS
 M: Corentin Chary 
 L: acpi4asus-u...@lists.sourceforge.net
-- 
1.8.3.1



[PATCH v11 6/8] ARM: dts: Aspeed: AST2500: Update XDMA engine node

2020-05-05 Thread Eddie James
Correct the pcie-device property, and add the Aspeed SCU interrupt
controller include.

Signed-off-by: Eddie James 
---
 arch/arm/boot/dts/aspeed-g5.dtsi | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
index 284face..8d9eeef 100644
--- a/arch/arm/boot/dts/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed-g5.dtsi
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0+
 #include 
+#include 
 
 / {
model = "Aspeed BMC";
@@ -267,8 +268,8 @@
reg = <0x1e6e7000 0x100>;
clocks = < ASPEED_CLK_GATE_BCLK>;
resets = < ASPEED_RESET_XDMA>;
-   interrupts-extended = < 6>, <_ic 2>;
-   pcie-device = "bmc";
+   interrupts-extended = < 6>, <_ic 
ASPEED_AST2500_SCU_IC_PCIE_RESET_LO_TO_HI>;
+   aspeed,pcie-device = "bmc";
aspeed,scu = <>;
status = "disabled";
};
-- 
1.8.3.1



[PATCH v11 3/8] soc: aspeed: xdma: Add user interface

2020-05-05 Thread Eddie James
This commits adds a miscdevice to provide a user interface to the XDMA
engine. The interface provides the write operation to start DMA
operations. The DMA parameters are passed as the data to the write call.
The actual data to transfer is NOT passed through write. Note that both
directions of DMA operation are accomplished through the write command;
BMC to host and host to BMC.

The XDMA driver reserves an area of physical memory for DMA operations,
as the XDMA engine is restricted to accessing certain physical memory
areas on some platforms. This memory forms a pool from which users can
allocate pages for their usage with calls to mmap. The space allocated
by a client will be the space used in the DMA operation. For an
"upstream" (BMC to host) operation, the data in the client's area will
be transferred to the host. For a "downstream" (host to BMC) operation,
the host data will be placed in the client's memory area.

Poll is also provided in order to determine when the DMA operation is
complete for non-blocking IO.

Signed-off-by: Eddie James 
Reviewed-by: Andrew Jeffery 
---
 drivers/soc/aspeed/aspeed-xdma.c | 218 +++
 1 file changed, 218 insertions(+)

diff --git a/drivers/soc/aspeed/aspeed-xdma.c b/drivers/soc/aspeed/aspeed-xdma.c
index da78149..b4d4d34 100644
--- a/drivers/soc/aspeed/aspeed-xdma.c
+++ b/drivers/soc/aspeed/aspeed-xdma.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -235,6 +236,8 @@ struct aspeed_xdma {
dma_addr_t mem_coherent;
dma_addr_t cmdq_phys;
struct gen_pool *pool;
+
+   struct miscdevice misc;
 };
 
 struct aspeed_xdma_client {
@@ -553,6 +556,211 @@ static irqreturn_t aspeed_xdma_pcie_irq(int irq, void 
*arg)
return IRQ_HANDLED;
 }
 
+static ssize_t aspeed_xdma_write(struct file *file, const char __user *buf,
+size_t len, loff_t *offset)
+{
+   int rc;
+   unsigned int num_cmds;
+   struct aspeed_xdma_op op;
+   struct aspeed_xdma_cmd cmds[2];
+   struct aspeed_xdma_client *client = file->private_data;
+   struct aspeed_xdma *ctx = client->ctx;
+
+   if (len != sizeof(op))
+   return -EINVAL;
+
+   rc = copy_from_user(, buf, len);
+   if (rc)
+   return rc;
+
+   if (!op.len || op.len > client->size ||
+   op.direction > ASPEED_XDMA_DIRECTION_UPSTREAM)
+   return -EINVAL;
+
+   num_cmds = ctx->chip->set_cmd(ctx, cmds, , client->phys);
+   do {
+   rc = aspeed_xdma_start(ctx, num_cmds, cmds, !!op.direction,
+  client);
+   if (!rc)
+   break;
+
+   if ((file->f_flags & O_NONBLOCK) || rc != -EBUSY)
+   return rc;
+
+   rc = wait_event_interruptible(ctx->wait,
+ !(ctx->current_client ||
+   ctx->in_reset));
+   } while (!rc);
+
+   if (rc)
+   return -EINTR;
+
+   if (!(file->f_flags & O_NONBLOCK)) {
+   rc = wait_event_interruptible(ctx->wait, !client->in_progress);
+   if (rc)
+   return -EINTR;
+
+   if (client->error)
+   return -EIO;
+   }
+
+   return len;
+}
+
+static __poll_t aspeed_xdma_poll(struct file *file,
+struct poll_table_struct *wait)
+{
+   __poll_t mask = 0;
+   __poll_t req = poll_requested_events(wait);
+   struct aspeed_xdma_client *client = file->private_data;
+   struct aspeed_xdma *ctx = client->ctx;
+
+   if (req & (EPOLLIN | EPOLLRDNORM)) {
+   if (READ_ONCE(client->in_progress))
+   poll_wait(file, >wait, wait);
+
+   if (!READ_ONCE(client->in_progress)) {
+   if (READ_ONCE(client->error))
+   mask |= EPOLLERR;
+   else
+   mask |= EPOLLIN | EPOLLRDNORM;
+   }
+   }
+
+   if (req & (EPOLLOUT | EPOLLWRNORM)) {
+   if (READ_ONCE(ctx->current_client))
+   poll_wait(file, >wait, wait);
+
+   if (!READ_ONCE(ctx->current_client))
+   mask |= EPOLLOUT | EPOLLWRNORM;
+   }
+
+   return mask;
+}
+
+static void aspeed_xdma_vma_close(struct vm_area_struct *vma)
+{
+   int rc;
+   struct aspeed_xdma_client *client = vma->vm_private_data;
+
+   rc = wait_event_interruptible(client->ctx->wait, !client->in_progress);
+   if (rc)
+   return;
+
+   gen_pool_free(client->ctx->pool, (unsigned long)client->virt,
+ client->size);
+
+   cli

[PATCH v11 2/8] soc: aspeed: Add XDMA Engine Driver

2020-05-05 Thread Eddie James
The XDMA engine embedded in the AST2500 and AST2600 SOCs performs PCI
DMA operations between the SOC (acting as a BMC) and a host processor
in a server.

This commit adds a driver to control the XDMA engine and adds functions
to initialize the hardware and memory and start DMA operations.

Signed-off-by: Eddie James 
Reviewed-by: Andrew Jeffery 
---
 MAINTAINERS  |   2 +
 drivers/soc/aspeed/Kconfig   |   8 +
 drivers/soc/aspeed/Makefile  |   1 +
 drivers/soc/aspeed/aspeed-xdma.c | 955 +++
 include/uapi/linux/aspeed-xdma.h |  38 ++
 5 files changed, 1004 insertions(+)
 create mode 100644 drivers/soc/aspeed/aspeed-xdma.c
 create mode 100644 include/uapi/linux/aspeed-xdma.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 6a421fd..5d6c8b3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2785,6 +2785,8 @@ M:Eddie James 
 L: linux-asp...@lists.ozlabs.org (moderated for non-subscribers)
 S: Maintained
 F: Documentation/devicetree/bindings/soc/aspeed/xdma.yaml
+F: drivers/soc/aspeed/aspeed-xdma.c
+F: include/uapi/linux/aspeed-xdma.h
 
 ASUS NOTEBOOKS AND EEEPC ACPI/WMI EXTRAS DRIVERS
 M: Corentin Chary 
diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig
index 323e177..2a6c16f 100644
--- a/drivers/soc/aspeed/Kconfig
+++ b/drivers/soc/aspeed/Kconfig
@@ -29,4 +29,12 @@ config ASPEED_P2A_CTRL
  ioctl()s, the driver also provides an interface for userspace 
mappings to
  a pre-defined region.
 
+config ASPEED_XDMA
+   tristate "Aspeed XDMA Engine Driver"
+   depends on SOC_ASPEED && REGMAP && MFD_SYSCON && HAS_DMA
+   help
+ Enable support for the Aspeed XDMA Engine found on the Aspeed AST2XXX
+ SOCs. The XDMA engine can perform automatic PCI DMA operations
+ between the AST2XXX (acting as a BMC) and a host processor.
+
 endmenu
diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile
index b64be47..977b046 100644
--- a/drivers/soc/aspeed/Makefile
+++ b/drivers/soc/aspeed/Makefile
@@ -2,3 +2,4 @@
 obj-$(CONFIG_ASPEED_LPC_CTRL)  += aspeed-lpc-ctrl.o
 obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
 obj-$(CONFIG_ASPEED_P2A_CTRL)  += aspeed-p2a-ctrl.o
+obj-$(CONFIG_ASPEED_XDMA)  += aspeed-xdma.o
diff --git a/drivers/soc/aspeed/aspeed-xdma.c b/drivers/soc/aspeed/aspeed-xdma.c
new file mode 100644
index 000..da78149
--- /dev/null
+++ b/drivers/soc/aspeed/aspeed-xdma.c
@@ -0,0 +1,955 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// Copyright IBM Corp 2019
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEVICE_NAME"aspeed-xdma"
+
+#define SCU_AST2600_MISC_CTRL  0x0c0
+#define  SCU_AST2600_MISC_CTRL_XDMA_BMC BIT(8)
+
+#define SCU_AST2500_PCIE_CONF  0x180
+#define SCU_AST2600_PCIE_CONF  0xc20
+#define  SCU_PCIE_CONF_VGA_EN   BIT(0)
+#define  SCU_PCIE_CONF_VGA_EN_MMIO  BIT(1)
+#define  SCU_PCIE_CONF_VGA_EN_LPC   BIT(2)
+#define  SCU_PCIE_CONF_VGA_EN_MSI   BIT(3)
+#define  SCU_PCIE_CONF_VGA_EN_MCTP  BIT(4)
+#define  SCU_PCIE_CONF_VGA_EN_IRQ   BIT(5)
+#define  SCU_PCIE_CONF_VGA_EN_DMA   BIT(6)
+#define  SCU_PCIE_CONF_BMC_EN   BIT(8)
+#define  SCU_PCIE_CONF_BMC_EN_MMIO  BIT(9)
+#define  SCU_PCIE_CONF_BMC_EN_MSI   BIT(11)
+#define  SCU_PCIE_CONF_BMC_EN_MCTP  BIT(12)
+#define  SCU_PCIE_CONF_BMC_EN_IRQ   BIT(13)
+#define  SCU_PCIE_CONF_BMC_EN_DMA   BIT(14)
+
+#define SCU_AST2500_BMC_CLASS_REV  0x19c
+#define SCU_AST2600_BMC_CLASS_REV  0xc68
+#define  SCU_BMC_CLASS_REV_XDMA 0xff01
+
+#define XDMA_CMDQ_SIZE PAGE_SIZE
+#define XDMA_NUM_CMDS  \
+   (XDMA_CMDQ_SIZE / sizeof(struct aspeed_xdma_cmd))
+
+/* Aspeed specification requires 100us after disabling the reset */
+#define XDMA_ENGINE_SETUP_TIME_MAX_US  1000
+#define XDMA_ENGINE_SETUP_TIME_MIN_US  100
+
+#define XDMA_CMD_AST2500_PITCH_SHIFT   3
+#define XDMA_CMD_AST2500_PITCH_BMC GENMASK_ULL(62, 51)
+#define XDMA_CMD_AST2500_PITCH_HOSTGENMASK_ULL(46, 35)
+#define XDMA_CMD_AST2500_PITCH_UPSTREAMBIT_ULL(31)
+#define XDMA_CMD_AST2500_PITCH_ADDRGENMASK_ULL(29, 4)
+#define XDMA_CMD_AST2500_PITCH_ID  BIT_ULL(0)
+#define XDMA_CMD_AST2500_CMD_IRQ_ENBIT_ULL(31)
+#define XDMA_CMD_AST2500_CMD_LINE_NO   GENMASK_ULL(27, 16)
+#define XDMA_CMD_AST250

[PATCH v11 5/8] ARM: dts: Aspeed: AST2600: Update XDMA engine node

2020-05-05 Thread Eddie James
Add the PCI-E root complex reset, correct the pcie-device property, and
add the Aspeed SCU interrupt controller include.

Signed-off-by: Eddie James 
---
 arch/arm/boot/dts/aspeed-g6.dtsi | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
index 1ffc1517..86a8e94 100644
--- a/arch/arm/boot/dts/aspeed-g6.dtsi
+++ b/arch/arm/boot/dts/aspeed-g6.dtsi
@@ -2,6 +2,7 @@
 // Copyright 2019 IBM Corp.
 
 #include 
+#include 
 #include 
 
 / {
@@ -342,10 +343,11 @@
compatible = "aspeed,ast2600-xdma";
reg = <0x1e6e7000 0x100>;
clocks = < ASPEED_CLK_GATE_BCLK>;
-   resets = < ASPEED_RESET_DEV_XDMA>;
+   resets = < ASPEED_RESET_DEV_XDMA>, 
< ASPEED_RESET_RC_XDMA>;
+   reset-names = "device", "root-complex";
interrupts-extended = < GIC_SPI 6 
IRQ_TYPE_LEVEL_HIGH>,
- <_ic0 2>;
-   pcie-device = "bmc";
+ <_ic0 
ASPEED_AST2600_SCU_IC0_PCIE_PERST_LO_TO_HI>;
+   aspeed,pcie-device = "bmc";
aspeed,scu = <>;
status = "disabled";
};
-- 
1.8.3.1



[PATCH v11 8/8] ARM: dts: Aspeed: Tacoma: Enable XDMA engine

2020-05-05 Thread Eddie James
Add a reserved memory node for the VGA memory. Add the XDMA engine node,
enable it, and point it's memory region to the VGA memory.

Signed-off-by: Eddie James 
---
 arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts 
b/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts
index 47293a5..d336dd4 100644
--- a/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts
@@ -29,6 +29,12 @@
no-map;
reg = <0xb800 0x400>; /* 64M */
};
+
+   vga_memory: region@bf00 {
+   no-map;
+   compatible = "shared-dma-pool";
+   reg = <0xbf00 0x0100>;  /* 16M */
+   };
};
 
gpio-keys {
@@ -804,3 +810,8 @@
pinctrl-0 = <_lpc_default>,
<_lsirq_default>;
 };
+
+ {
+   status = "okay";
+   memory-region = <_memory>;
+};
-- 
1.8.3.1



[PATCH v11 7/8] ARM: dts: Aspeed: Witherspoon: Enable XDMA engine

2020-05-05 Thread Eddie James
Add a reserved memory node for the VGA memory. Add the XDMA engine node,
enable it, and point it's memory region to the VGA memory.

Signed-off-by: Eddie James 
---
 arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts 
b/arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts
index a0f99e3..85d58a6 100644
--- a/arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts
@@ -27,6 +27,12 @@
reg = <0x9800 0x0400>; /* 64M */
};
 
+   vga_memory: region@9f00 {
+   no-map;
+   compatible = "shared-dma-pool";
+   reg = <0x9f00 0x0100>; /* 16M */
+   };
+
gfx_memory: framebuffer {
size = <0x0100>;
alignment = <0x0100>;
@@ -690,4 +696,9 @@
memory-region = <_engine_memory>;
 };
 
+ {
+   status = "okay";
+   memory-region = <_memory>;
+};
+
 #include "ibm-power9-dual.dtsi"
-- 
1.8.3.1



[PATCH 3/3] hwmon: (occ) Add new temperature sensor type

2020-05-01 Thread Eddie James
The latest version of the On-Chip Controller (OCC) has a different
format for the temperature sensor data. Add a new temperature sensor
version to handle this data.

Signed-off-by: Eddie James 
---
 drivers/hwmon/occ/common.c | 75 ++
 1 file changed, 75 insertions(+)

diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c
index 30e18eb60da7..52af0e728232 100644
--- a/drivers/hwmon/occ/common.c
+++ b/drivers/hwmon/occ/common.c
@@ -41,6 +41,14 @@ struct temp_sensor_2 {
u8 value;
 } __packed;
 
+struct temp_sensor_10 {
+   u32 sensor_id;
+   u8 fru_type;
+   u8 value;
+   u8 throttle;
+   u8 reserved;
+} __packed;
+
 struct freq_sensor_1 {
u16 sensor_id;
u16 value;
@@ -307,6 +315,60 @@ static ssize_t occ_show_temp_2(struct device *dev,
return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
 }
 
+static ssize_t occ_show_temp_10(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   int rc;
+   u32 val = 0;
+   struct temp_sensor_10 *temp;
+   struct occ *occ = dev_get_drvdata(dev);
+   struct occ_sensors *sensors = >sensors;
+   struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+   rc = occ_update_response(occ);
+   if (rc)
+   return rc;
+
+   temp = ((struct temp_sensor_10 *)sensors->temp.data) + sattr->index;
+
+   switch (sattr->nr) {
+   case 0:
+   val = get_unaligned_be32(>sensor_id);
+   break;
+   case 1:
+   val = temp->value;
+   if (val == OCC_TEMP_SENSOR_FAULT)
+   return -EREMOTEIO;
+
+   /*
+* VRM doesn't return temperature, only alarm bit. This
+* attribute maps to tempX_alarm instead of tempX_input for
+* VRM
+*/
+   if (temp->fru_type != OCC_FRU_TYPE_VRM) {
+   /* sensor not ready */
+   if (val == 0)
+   return -EAGAIN;
+
+   val *= 1000;
+   }
+   break;
+   case 2:
+   val = temp->fru_type;
+   break;
+   case 3:
+   val = temp->value == OCC_TEMP_SENSOR_FAULT;
+   break;
+   case 4:
+   val = temp->throttle * 1000;
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
+}
+
 static ssize_t occ_show_freq_1(struct device *dev,
   struct device_attribute *attr, char *buf)
 {
@@ -745,6 +807,10 @@ static int occ_setup_sensor_attrs(struct occ *occ)
num_attrs += (sensors->temp.num_sensors * 4);
show_temp = occ_show_temp_2;
break;
+   case 0x10:
+   num_attrs += (sensors->temp.num_sensors * 5);
+   show_temp = occ_show_temp_10;
+   break;
default:
sensors->temp.num_sensors = 0;
}
@@ -844,6 +910,15 @@ static int occ_setup_sensor_attrs(struct occ *occ)
attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
 show_temp, NULL, 3, i);
attr++;
+
+   if (sensors->temp.version == 0x10) {
+   snprintf(attr->name, sizeof(attr->name),
+"temp%d_max", s);
+   attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+show_temp, NULL,
+4, i);
+   attr++;
+   }
}
}
 
-- 
2.24.0



[PATCH 0/3] occ: Add support for P10

2020-05-01 Thread Eddie James
The OCC in the P10 has a number of differences from the P9. Add some logic to
handle the differences in accessing the OCC from the service processor, and
support the new temperature sensor type.

Eddie James (3):
  dt-bindings: fsi: Add P10 OCC device documentation
  fsi: occ: Add support for P10
  hwmon: (occ) Add new temperature sensor type

 .../devicetree/bindings/fsi/ibm,p9-occ.txt|  12 +-
 drivers/fsi/fsi-occ.c | 126 +-
 drivers/hwmon/occ/common.c|  75 +++
 3 files changed, 173 insertions(+), 40 deletions(-)

-- 
2.24.0



[PATCH 2/3] fsi: occ: Add support for P10

2020-05-01 Thread Eddie James
The P10 OCC has a different SRAM address for the command and response
buffers. In addition, the SBE commands to access the SRAM have changed
format. Add versioning to the driver to handle these differences.

Signed-off-by: Eddie James 
---
 drivers/fsi/fsi-occ.c | 126 ++
 1 file changed, 92 insertions(+), 34 deletions(-)

diff --git a/drivers/fsi/fsi-occ.c b/drivers/fsi/fsi-occ.c
index 7da9c81759ac..942eff4032b0 100644
--- a/drivers/fsi/fsi-occ.c
+++ b/drivers/fsi/fsi-occ.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -24,8 +25,13 @@
 #define OCC_CMD_DATA_BYTES 4090
 #define OCC_RESP_DATA_BYTES4089
 
-#define OCC_SRAM_CMD_ADDR  0xFFFBE000
-#define OCC_SRAM_RSP_ADDR  0xFFFBF000
+#define OCC_P9_SRAM_CMD_ADDR   0xFFFBE000
+#define OCC_P9_SRAM_RSP_ADDR   0xFFFBF000
+
+#define OCC_P10_SRAM_CMD_ADDR  0xD000
+#define OCC_P10_SRAM_RSP_ADDR  0xE000
+
+#define OCC_P10_SRAM_MODE  0x58/* Normal mode, OCB channel 2 */
 
 /*
  * Assume we don't have much FFDC, if we do we'll overflow and
@@ -37,11 +43,14 @@
 #define OCC_TIMEOUT_MS 1000
 #define OCC_CMD_IN_PRG_WAIT_MS 50
 
+enum versions { occ_p9, occ_p10 };
+
 struct occ {
struct device *dev;
struct device *sbefifo;
char name[32];
int idx;
+   enum versions version;
struct miscdevice mdev;
struct mutex occ_lock;
 };
@@ -235,29 +244,43 @@ static int occ_verify_checksum(struct occ_response *resp, 
u16 data_length)
return 0;
 }
 
-static int occ_getsram(struct occ *occ, u32 address, void *data, ssize_t len)
+static int occ_getsram(struct occ *occ, u32 offset, void *data, ssize_t len)
 {
u32 data_len = ((len + 7) / 8) * 8; /* must be multiples of 8 B */
-   size_t resp_len, resp_data_len;
-   __be32 *resp, cmd[5];
-   int rc;
+   size_t cmd_len, resp_len, resp_data_len;
+   __be32 *resp, cmd[6];
+   int idx = 0, rc;
 
/*
 * Magic sequence to do SBE getsram command. SBE will fetch data from
 * specified SRAM address.
 */
-   cmd[0] = cpu_to_be32(0x5);
+   switch (occ->version) {
+   default:
+   case occ_p9:
+   cmd_len = 5;
+   cmd[2] = cpu_to_be32(1);/* Normal mode */
+   cmd[3] = cpu_to_be32(OCC_P9_SRAM_RSP_ADDR + offset);
+   break;
+   case occ_p10:
+   idx = 1;
+   cmd_len = 6;
+   cmd[2] = cpu_to_be32(OCC_P10_SRAM_MODE);
+   cmd[3] = 0;
+   cmd[4] = cpu_to_be32(OCC_P10_SRAM_RSP_ADDR + offset);
+   break;
+   }
+
+   cmd[0] = cpu_to_be32(cmd_len);
cmd[1] = cpu_to_be32(SBEFIFO_CMD_GET_OCC_SRAM);
-   cmd[2] = cpu_to_be32(1);
-   cmd[3] = cpu_to_be32(address);
-   cmd[4] = cpu_to_be32(data_len);
+   cmd[4 + idx] = cpu_to_be32(data_len);
 
resp_len = (data_len >> 2) + OCC_SBE_STATUS_WORDS;
resp = kzalloc(resp_len << 2, GFP_KERNEL);
if (!resp)
return -ENOMEM;
 
-   rc = sbefifo_submit(occ->sbefifo, cmd, 5, resp, _len);
+   rc = sbefifo_submit(occ->sbefifo, cmd, cmd_len, resp, _len);
if (rc)
goto free;
 
@@ -287,20 +310,21 @@ static int occ_getsram(struct occ *occ, u32 address, void 
*data, ssize_t len)
return rc;
 }
 
-static int occ_putsram(struct occ *occ, u32 address, const void *data,
-  ssize_t len)
+static int occ_putsram(struct occ *occ, const void *data, ssize_t len)
 {
size_t cmd_len, buf_len, resp_len, resp_data_len;
u32 data_len = ((len + 7) / 8) * 8; /* must be multiples of 8 B */
__be32 *buf;
-   int rc;
+   int idx = 0, rc;
+
+   cmd_len = (occ->version == occ_p10) ? 6 : 5;
 
/*
 * We use the same buffer for command and response, make
 * sure it's big enough
 */
resp_len = OCC_SBE_STATUS_WORDS;
-   cmd_len = (data_len >> 2) + 5;
+   cmd_len += data_len >> 2;
buf_len = max(cmd_len, resp_len);
buf = kzalloc(buf_len << 2, GFP_KERNEL);
if (!buf)
@@ -312,11 +336,23 @@ static int occ_putsram(struct occ *occ, u32 address, 
const void *data,
 */
buf[0] = cpu_to_be32(cmd_len);
buf[1] = cpu_to_be32(SBEFIFO_CMD_PUT_OCC_SRAM);
-   buf[2] = cpu_to_be32(1);
-   buf[3] = cpu_to_be32(address);
-   buf[4] = cpu_to_be32(data_len);
 
-   memcpy([5], data, len);
+   switch (occ->version) {
+   default:
+   case occ_p9:
+   buf[2] = cpu_to_be32(1);/* Normal mode */
+   buf[3] = cpu_to_be32(OCC_P9_SRAM_CMD_ADDR);
+   break;
+   case occ_p10:
+   idx = 1;
+   buf[2] = cpu_to_be32(OCC_P10_SRAM_MODE);
+   buf[3] = 0;
+   buf[4] = cpu_to_be32(

[PATCH 1/3] dt-bindings: fsi: Add P10 OCC device documentation

2020-05-01 Thread Eddie James
Add the P10 compatible string.

Signed-off-by: Eddie James 
---
 Documentation/devicetree/bindings/fsi/ibm,p9-occ.txt | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/fsi/ibm,p9-occ.txt 
b/Documentation/devicetree/bindings/fsi/ibm,p9-occ.txt
index 99ca9862a586..e73358075a90 100644
--- a/Documentation/devicetree/bindings/fsi/ibm,p9-occ.txt
+++ b/Documentation/devicetree/bindings/fsi/ibm,p9-occ.txt
@@ -1,13 +1,13 @@
-Device-tree bindings for FSI-attached POWER9 On-Chip Controller (OCC)
--
+Device-tree bindings for FSI-attached POWER9/POWER10 On-Chip Controller (OCC)
+-
 
-This is the binding for the P9 On-Chip Controller accessed over FSI from a
-service processor. See fsi.txt for details on bindings for FSI slave and CFAM
+This is the binding for the P9 or P10 On-Chip Controller accessed over FSI from
+a service processor. See fsi.txt for details on bindings for FSI slave and CFAM
 nodes. The OCC is not an FSI slave device itself, rather it is accessed
-through the SBE fifo.
+through the SBE FIFO.
 
 Required properties:
- - compatible = "ibm,p9-occ"
+ - compatible = "ibm,p9-occ" or "ibm,p10-occ"
 
 Examples:
 
-- 
2.24.0



[PATCH 1/2] dt-bindings: hwmon: Document ibm,cffps compatible string

2019-10-09 Thread Eddie James
Document this string that indicates that any version of the power supply
may be connected. In this case, the driver must detect the version
automatically.

Signed-off-by: Eddie James 
---
 Documentation/devicetree/bindings/hwmon/ibm,cffps1.txt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/hwmon/ibm,cffps1.txt 
b/Documentation/devicetree/bindings/hwmon/ibm,cffps1.txt
index 1036f65..d9a2719 100644
--- a/Documentation/devicetree/bindings/hwmon/ibm,cffps1.txt
+++ b/Documentation/devicetree/bindings/hwmon/ibm,cffps1.txt
@@ -5,6 +5,9 @@ Required properties:
  - compatible  : Must be one of the following:
"ibm,cffps1"
"ibm,cffps2"
+   or "ibm,cffps" if the system
+   must support any version of the
+   power supply
  - reg = < I2C bus address >;  : Address of the power supply on the
  I2C bus.
 
-- 
1.8.3.1



[PATCH 0/2] hwmon: (pmbus/ibm-cffps) Add version detection capability

2019-10-09 Thread Eddie James
The IBM common form factor power supply driver may need to detect which PSU
version is connected, since some systems can use a variety of power supplies.
This series adds a new compatible string with no version number, and some code
to parse the CCIN of the PSU to determine which version is applicable.

Eddie James (2):
  dt-bindings: hwmon: Document ibm,cffps compatible string
  hwmon: (pmbus/ibm-cffps) Add version detection capability

 .../devicetree/bindings/hwmon/ibm,cffps1.txt   |  3 ++
 drivers/hwmon/pmbus/ibm-cffps.c| 37 +++---
 2 files changed, 36 insertions(+), 4 deletions(-)

-- 
1.8.3.1



[PATCH v2 4/4] ARM: dts: aspeed: ast2600: Add SCU interrupt controllers

2019-09-27 Thread Eddie James
Add nodes for the interrupt controllers provided by the SCU.

Signed-off-by: Eddie James 
---
 arch/arm/boot/dts/aspeed-g6.dtsi | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
index 3a1422f..d89f1e6 100644
--- a/arch/arm/boot/dts/aspeed-g6.dtsi
+++ b/arch/arm/boot/dts/aspeed-g6.dtsi
@@ -159,6 +159,24 @@
compatible = "aspeed,ast2600-smpmem";
reg = <0x180 0x40>;
};
+
+   scu_ic0: interrupt-controller@0 {
+   #interrupt-cells = <1>;
+   compatible = "aspeed,ast2600-scu-ic0";
+   reg = <0x560 0x4>;
+   interrupt-parent = <>;
+   interrupts = ;
+   interrupt-controller;
+   };
+
+   scu_ic1: interrupt-controller@1 {
+   #interrupt-cells = <1>;
+   compatible = "aspeed,ast2600-scu-ic1";
+   reg = <0x570 0x4>;
+   interrupt-parent = <>;
+   interrupts = ;
+   interrupt-controller;
+   };
};
 
rng: hwrng@1e6e2524 {
-- 
1.8.3.1



  1   2   3   4   5   6   7   8   9   >