提交 819d38e9 编写于 作者: A Arnd Bergmann

Merge tag 'scpi-updates-4.17' of...

Merge tag 'scpi-updates-4.17' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into next/drivers

Pull "ARM SCPI updates/cleanups for v4.17" from Sudeep Holla:

1. Fixes to get rid of sparse warnings
2. Use of FIELD_GET and GENMASK for better subfields handling
3. Make mbox_free_channels device-managed helping in removing unnecessary code
4. Various other cleanups to simplify and improve code readability

Note that similar set of changes were merged in v4.15, however got reverted
through the commit 81faa556 ("firmware: arm_scpi: Revert updates made
during v4.15 merge window") for reasons mentioned in that commit.

This is the resend with the culprit patch removed. Kevin Hilman tested this
series on Amlogic and reported it to be fine.

* tag 'scpi-updates-4.17' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux:
  firmware: arm_scpi: improve info message for pre-1.0 firmware
  firmware: arm_scpi: use FIELD_GET/_PREP to simplify macro definitions
  firmware: arm_scpi: remove struct sensor_capabilities
  firmware: arm_scpi: fix incorrect __iomem accesses using correct accessors
  firmware: arm_scpi: remove all single element structures
  firmware: arm_scpi: drop unnecessary type cast to scpi_shared_mem
  firmware: arm_scpi: improve struct sensor_value
  firmware: arm_scpi: improve handling of protocol and firmware version subfields
  firmware: arm_scpi: improve struct dvfs_info to make code better readable
  firmware: arm_scpi: make scpi_probe completely device-managed
  firmware: arm_scpi: make freeing mbox channels device-managed
  firmware: arm_scpi: remove two unneeded devm_kfree's in scpi_remove
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/bitmap.h> #include <linux/bitmap.h>
#include <linux/bitfield.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/export.h> #include <linux/export.h>
...@@ -45,48 +46,32 @@ ...@@ -45,48 +46,32 @@
#include <linux/sort.h> #include <linux/sort.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#define CMD_ID_SHIFT 0 #define CMD_ID_MASK GENMASK(6, 0)
#define CMD_ID_MASK 0x7f #define CMD_TOKEN_ID_MASK GENMASK(15, 8)
#define CMD_TOKEN_ID_SHIFT 8 #define CMD_DATA_SIZE_MASK GENMASK(24, 16)
#define CMD_TOKEN_ID_MASK 0xff #define CMD_LEGACY_DATA_SIZE_MASK GENMASK(28, 20)
#define CMD_DATA_SIZE_SHIFT 16 #define PACK_SCPI_CMD(cmd_id, tx_sz) \
#define CMD_DATA_SIZE_MASK 0x1ff (FIELD_PREP(CMD_ID_MASK, cmd_id) | \
#define CMD_LEGACY_DATA_SIZE_SHIFT 20 FIELD_PREP(CMD_DATA_SIZE_MASK, tx_sz))
#define CMD_LEGACY_DATA_SIZE_MASK 0x1ff #define PACK_LEGACY_SCPI_CMD(cmd_id, tx_sz) \
#define PACK_SCPI_CMD(cmd_id, tx_sz) \ (FIELD_PREP(CMD_ID_MASK, cmd_id) | \
((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) | \ FIELD_PREP(CMD_LEGACY_DATA_SIZE_MASK, tx_sz))
(((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
#define ADD_SCPI_TOKEN(cmd, token) \ #define CMD_SIZE(cmd) FIELD_GET(CMD_DATA_SIZE_MASK, cmd)
((cmd) |= (((token) & CMD_TOKEN_ID_MASK) << CMD_TOKEN_ID_SHIFT)) #define CMD_UNIQ_MASK (CMD_TOKEN_ID_MASK | CMD_ID_MASK)
#define PACK_LEGACY_SCPI_CMD(cmd_id, tx_sz) \
((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) | \
(((tx_sz) & CMD_LEGACY_DATA_SIZE_MASK) << CMD_LEGACY_DATA_SIZE_SHIFT))
#define CMD_SIZE(cmd) (((cmd) >> CMD_DATA_SIZE_SHIFT) & CMD_DATA_SIZE_MASK)
#define CMD_LEGACY_SIZE(cmd) (((cmd) >> CMD_LEGACY_DATA_SIZE_SHIFT) & \
CMD_LEGACY_DATA_SIZE_MASK)
#define CMD_UNIQ_MASK (CMD_TOKEN_ID_MASK << CMD_TOKEN_ID_SHIFT | CMD_ID_MASK)
#define CMD_XTRACT_UNIQ(cmd) ((cmd) & CMD_UNIQ_MASK) #define CMD_XTRACT_UNIQ(cmd) ((cmd) & CMD_UNIQ_MASK)
#define SCPI_SLOT 0 #define SCPI_SLOT 0
#define MAX_DVFS_DOMAINS 8 #define MAX_DVFS_DOMAINS 8
#define MAX_DVFS_OPPS 16 #define MAX_DVFS_OPPS 16
#define DVFS_LATENCY(hdr) (le32_to_cpu(hdr) >> 16)
#define DVFS_OPP_COUNT(hdr) ((le32_to_cpu(hdr) >> 8) & 0xff) #define PROTO_REV_MAJOR_MASK GENMASK(31, 16)
#define PROTO_REV_MINOR_MASK GENMASK(15, 0)
#define PROTOCOL_REV_MINOR_BITS 16
#define PROTOCOL_REV_MINOR_MASK ((1U << PROTOCOL_REV_MINOR_BITS) - 1) #define FW_REV_MAJOR_MASK GENMASK(31, 24)
#define PROTOCOL_REV_MAJOR(x) ((x) >> PROTOCOL_REV_MINOR_BITS) #define FW_REV_MINOR_MASK GENMASK(23, 16)
#define PROTOCOL_REV_MINOR(x) ((x) & PROTOCOL_REV_MINOR_MASK) #define FW_REV_PATCH_MASK GENMASK(15, 0)
#define FW_REV_MAJOR_BITS 24
#define FW_REV_MINOR_BITS 16
#define FW_REV_PATCH_MASK ((1U << FW_REV_MINOR_BITS) - 1)
#define FW_REV_MINOR_MASK ((1U << FW_REV_MAJOR_BITS) - 1)
#define FW_REV_MAJOR(x) ((x) >> FW_REV_MAJOR_BITS)
#define FW_REV_MINOR(x) (((x) & FW_REV_MINOR_MASK) >> FW_REV_MINOR_BITS)
#define FW_REV_PATCH(x) ((x) & FW_REV_PATCH_MASK)
#define MAX_RX_TIMEOUT (msecs_to_jiffies(30)) #define MAX_RX_TIMEOUT (msecs_to_jiffies(30))
...@@ -311,10 +296,6 @@ struct clk_get_info { ...@@ -311,10 +296,6 @@ struct clk_get_info {
u8 name[20]; u8 name[20];
} __packed; } __packed;
struct clk_get_value {
__le32 rate;
} __packed;
struct clk_set_value { struct clk_set_value {
__le16 id; __le16 id;
__le16 reserved; __le16 reserved;
...@@ -328,7 +309,9 @@ struct legacy_clk_set_value { ...@@ -328,7 +309,9 @@ struct legacy_clk_set_value {
} __packed; } __packed;
struct dvfs_info { struct dvfs_info {
__le32 header; u8 domain;
u8 opp_count;
__le16 latency;
struct { struct {
__le32 freq; __le32 freq;
__le32 m_volt; __le32 m_volt;
...@@ -340,10 +323,6 @@ struct dvfs_set { ...@@ -340,10 +323,6 @@ struct dvfs_set {
u8 index; u8 index;
} __packed; } __packed;
struct sensor_capabilities {
__le16 sensors;
} __packed;
struct _scpi_sensor_info { struct _scpi_sensor_info {
__le16 sensor_id; __le16 sensor_id;
u8 class; u8 class;
...@@ -351,11 +330,6 @@ struct _scpi_sensor_info { ...@@ -351,11 +330,6 @@ struct _scpi_sensor_info {
char name[20]; char name[20];
}; };
struct sensor_value {
__le32 lo_val;
__le32 hi_val;
} __packed;
struct dev_pstate_set { struct dev_pstate_set {
__le16 dev_id; __le16 dev_id;
u8 pstate; u8 pstate;
...@@ -419,19 +393,20 @@ static void scpi_process_cmd(struct scpi_chan *ch, u32 cmd) ...@@ -419,19 +393,20 @@ static void scpi_process_cmd(struct scpi_chan *ch, u32 cmd)
unsigned int len; unsigned int len;
if (scpi_info->is_legacy) { if (scpi_info->is_legacy) {
struct legacy_scpi_shared_mem *mem = ch->rx_payload; struct legacy_scpi_shared_mem __iomem *mem =
ch->rx_payload;
/* RX Length is not replied by the legacy Firmware */ /* RX Length is not replied by the legacy Firmware */
len = match->rx_len; len = match->rx_len;
match->status = le32_to_cpu(mem->status); match->status = ioread32(&mem->status);
memcpy_fromio(match->rx_buf, mem->payload, len); memcpy_fromio(match->rx_buf, mem->payload, len);
} else { } else {
struct scpi_shared_mem *mem = ch->rx_payload; struct scpi_shared_mem __iomem *mem = ch->rx_payload;
len = min(match->rx_len, CMD_SIZE(cmd)); len = min_t(unsigned int, match->rx_len, CMD_SIZE(cmd));
match->status = le32_to_cpu(mem->status); match->status = ioread32(&mem->status);
memcpy_fromio(match->rx_buf, mem->payload, len); memcpy_fromio(match->rx_buf, mem->payload, len);
} }
...@@ -445,11 +420,11 @@ static void scpi_process_cmd(struct scpi_chan *ch, u32 cmd) ...@@ -445,11 +420,11 @@ static void scpi_process_cmd(struct scpi_chan *ch, u32 cmd)
static void scpi_handle_remote_msg(struct mbox_client *c, void *msg) static void scpi_handle_remote_msg(struct mbox_client *c, void *msg)
{ {
struct scpi_chan *ch = container_of(c, struct scpi_chan, cl); struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
struct scpi_shared_mem *mem = ch->rx_payload; struct scpi_shared_mem __iomem *mem = ch->rx_payload;
u32 cmd = 0; u32 cmd = 0;
if (!scpi_info->is_legacy) if (!scpi_info->is_legacy)
cmd = le32_to_cpu(mem->command); cmd = ioread32(&mem->command);
scpi_process_cmd(ch, cmd); scpi_process_cmd(ch, cmd);
} }
...@@ -459,7 +434,7 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg) ...@@ -459,7 +434,7 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg)
unsigned long flags; unsigned long flags;
struct scpi_xfer *t = msg; struct scpi_xfer *t = msg;
struct scpi_chan *ch = container_of(c, struct scpi_chan, cl); struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
struct scpi_shared_mem *mem = (struct scpi_shared_mem *)ch->tx_payload; struct scpi_shared_mem __iomem *mem = ch->tx_payload;
if (t->tx_buf) { if (t->tx_buf) {
if (scpi_info->is_legacy) if (scpi_info->is_legacy)
...@@ -471,14 +446,14 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg) ...@@ -471,14 +446,14 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg)
if (t->rx_buf) { if (t->rx_buf) {
if (!(++ch->token)) if (!(++ch->token))
++ch->token; ++ch->token;
ADD_SCPI_TOKEN(t->cmd, ch->token); t->cmd |= FIELD_PREP(CMD_TOKEN_ID_MASK, ch->token);
spin_lock_irqsave(&ch->rx_lock, flags); spin_lock_irqsave(&ch->rx_lock, flags);
list_add_tail(&t->node, &ch->rx_pending); list_add_tail(&t->node, &ch->rx_pending);
spin_unlock_irqrestore(&ch->rx_lock, flags); spin_unlock_irqrestore(&ch->rx_lock, flags);
} }
if (!scpi_info->is_legacy) if (!scpi_info->is_legacy)
mem->command = cpu_to_le32(t->cmd); iowrite32(t->cmd, &mem->command);
} }
static struct scpi_xfer *get_scpi_xfer(struct scpi_chan *ch) static struct scpi_xfer *get_scpi_xfer(struct scpi_chan *ch)
...@@ -583,13 +558,13 @@ scpi_clk_get_range(u16 clk_id, unsigned long *min, unsigned long *max) ...@@ -583,13 +558,13 @@ scpi_clk_get_range(u16 clk_id, unsigned long *min, unsigned long *max)
static unsigned long scpi_clk_get_val(u16 clk_id) static unsigned long scpi_clk_get_val(u16 clk_id)
{ {
int ret; int ret;
struct clk_get_value clk; __le32 rate;
__le16 le_clk_id = cpu_to_le16(clk_id); __le16 le_clk_id = cpu_to_le16(clk_id);
ret = scpi_send_message(CMD_GET_CLOCK_VALUE, &le_clk_id, ret = scpi_send_message(CMD_GET_CLOCK_VALUE, &le_clk_id,
sizeof(le_clk_id), &clk, sizeof(clk)); sizeof(le_clk_id), &rate, sizeof(rate));
return ret ? ret : le32_to_cpu(clk.rate); return ret ? ret : le32_to_cpu(rate);
} }
static int scpi_clk_set_val(u16 clk_id, unsigned long rate) static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
...@@ -665,8 +640,8 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain) ...@@ -665,8 +640,8 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
if (!info) if (!info)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
info->count = DVFS_OPP_COUNT(buf.header); info->count = buf.opp_count;
info->latency = DVFS_LATENCY(buf.header) * 1000; /* uS to nS */ info->latency = le16_to_cpu(buf.latency) * 1000; /* uS to nS */
info->opps = kcalloc(info->count, sizeof(*opp), GFP_KERNEL); info->opps = kcalloc(info->count, sizeof(*opp), GFP_KERNEL);
if (!info->opps) { if (!info->opps) {
...@@ -713,9 +688,6 @@ static int scpi_dvfs_get_transition_latency(struct device *dev) ...@@ -713,9 +688,6 @@ static int scpi_dvfs_get_transition_latency(struct device *dev)
if (IS_ERR(info)) if (IS_ERR(info))
return PTR_ERR(info); return PTR_ERR(info);
if (!info->latency)
return 0;
return info->latency; return info->latency;
} }
...@@ -746,13 +718,13 @@ static int scpi_dvfs_add_opps_to_device(struct device *dev) ...@@ -746,13 +718,13 @@ static int scpi_dvfs_add_opps_to_device(struct device *dev)
static int scpi_sensor_get_capability(u16 *sensors) static int scpi_sensor_get_capability(u16 *sensors)
{ {
struct sensor_capabilities cap_buf; __le16 cap;
int ret; int ret;
ret = scpi_send_message(CMD_SENSOR_CAPABILITIES, NULL, 0, &cap_buf, ret = scpi_send_message(CMD_SENSOR_CAPABILITIES, NULL, 0, &cap,
sizeof(cap_buf)); sizeof(cap));
if (!ret) if (!ret)
*sensors = le16_to_cpu(cap_buf.sensors); *sensors = le16_to_cpu(cap);
return ret; return ret;
} }
...@@ -776,20 +748,19 @@ static int scpi_sensor_get_info(u16 sensor_id, struct scpi_sensor_info *info) ...@@ -776,20 +748,19 @@ static int scpi_sensor_get_info(u16 sensor_id, struct scpi_sensor_info *info)
static int scpi_sensor_get_value(u16 sensor, u64 *val) static int scpi_sensor_get_value(u16 sensor, u64 *val)
{ {
__le16 id = cpu_to_le16(sensor); __le16 id = cpu_to_le16(sensor);
struct sensor_value buf; __le64 value;
int ret; int ret;
ret = scpi_send_message(CMD_SENSOR_VALUE, &id, sizeof(id), ret = scpi_send_message(CMD_SENSOR_VALUE, &id, sizeof(id),
&buf, sizeof(buf)); &value, sizeof(value));
if (ret) if (ret)
return ret; return ret;
if (scpi_info->is_legacy) if (scpi_info->is_legacy)
/* only 32-bits supported, hi_val can be junk */ /* only 32-bits supported, upper 32 bits can be junk */
*val = le32_to_cpu(buf.lo_val); *val = le32_to_cpup((__le32 *)&value);
else else
*val = (u64)le32_to_cpu(buf.hi_val) << 32 | *val = le64_to_cpu(value);
le32_to_cpu(buf.lo_val);
return 0; return 0;
} }
...@@ -864,9 +835,9 @@ static ssize_t protocol_version_show(struct device *dev, ...@@ -864,9 +835,9 @@ static ssize_t protocol_version_show(struct device *dev,
{ {
struct scpi_drvinfo *scpi_info = dev_get_drvdata(dev); struct scpi_drvinfo *scpi_info = dev_get_drvdata(dev);
return sprintf(buf, "%d.%d\n", return sprintf(buf, "%lu.%lu\n",
PROTOCOL_REV_MAJOR(scpi_info->protocol_version), FIELD_GET(PROTO_REV_MAJOR_MASK, scpi_info->protocol_version),
PROTOCOL_REV_MINOR(scpi_info->protocol_version)); FIELD_GET(PROTO_REV_MINOR_MASK, scpi_info->protocol_version));
} }
static DEVICE_ATTR_RO(protocol_version); static DEVICE_ATTR_RO(protocol_version);
...@@ -875,10 +846,10 @@ static ssize_t firmware_version_show(struct device *dev, ...@@ -875,10 +846,10 @@ static ssize_t firmware_version_show(struct device *dev,
{ {
struct scpi_drvinfo *scpi_info = dev_get_drvdata(dev); struct scpi_drvinfo *scpi_info = dev_get_drvdata(dev);
return sprintf(buf, "%d.%d.%d\n", return sprintf(buf, "%lu.%lu.%lu\n",
FW_REV_MAJOR(scpi_info->firmware_version), FIELD_GET(FW_REV_MAJOR_MASK, scpi_info->firmware_version),
FW_REV_MINOR(scpi_info->firmware_version), FIELD_GET(FW_REV_MINOR_MASK, scpi_info->firmware_version),
FW_REV_PATCH(scpi_info->firmware_version)); FIELD_GET(FW_REV_PATCH_MASK, scpi_info->firmware_version));
} }
static DEVICE_ATTR_RO(firmware_version); static DEVICE_ATTR_RO(firmware_version);
...@@ -889,37 +860,26 @@ static struct attribute *versions_attrs[] = { ...@@ -889,37 +860,26 @@ static struct attribute *versions_attrs[] = {
}; };
ATTRIBUTE_GROUPS(versions); ATTRIBUTE_GROUPS(versions);
static void static void scpi_free_channels(void *data)
scpi_free_channels(struct device *dev, struct scpi_chan *pchan, int count)
{ {
struct scpi_drvinfo *info = data;
int i; int i;
for (i = 0; i < count && pchan->chan; i++, pchan++) { for (i = 0; i < info->num_chans; i++)
mbox_free_channel(pchan->chan); mbox_free_channel(info->channels[i].chan);
devm_kfree(dev, pchan->xfers);
devm_iounmap(dev, pchan->rx_payload);
}
} }
static int scpi_remove(struct platform_device *pdev) static int scpi_remove(struct platform_device *pdev)
{ {
int i; int i;
struct device *dev = &pdev->dev;
struct scpi_drvinfo *info = platform_get_drvdata(pdev); struct scpi_drvinfo *info = platform_get_drvdata(pdev);
scpi_info = NULL; /* stop exporting SCPI ops through get_scpi_ops */ scpi_info = NULL; /* stop exporting SCPI ops through get_scpi_ops */
of_platform_depopulate(dev);
sysfs_remove_groups(&dev->kobj, versions_groups);
scpi_free_channels(dev, info->channels, info->num_chans);
platform_set_drvdata(pdev, NULL);
for (i = 0; i < MAX_DVFS_DOMAINS && info->dvfs[i]; i++) { for (i = 0; i < MAX_DVFS_DOMAINS && info->dvfs[i]; i++) {
kfree(info->dvfs[i]->opps); kfree(info->dvfs[i]->opps);
kfree(info->dvfs[i]); kfree(info->dvfs[i]);
} }
devm_kfree(dev, info->channels);
devm_kfree(dev, info);
return 0; return 0;
} }
...@@ -952,7 +912,6 @@ static int scpi_probe(struct platform_device *pdev) ...@@ -952,7 +912,6 @@ static int scpi_probe(struct platform_device *pdev)
{ {
int count, idx, ret; int count, idx, ret;
struct resource res; struct resource res;
struct scpi_chan *scpi_chan;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
...@@ -969,13 +928,19 @@ static int scpi_probe(struct platform_device *pdev) ...@@ -969,13 +928,19 @@ static int scpi_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
scpi_chan = devm_kcalloc(dev, count, sizeof(*scpi_chan), GFP_KERNEL); scpi_info->channels = devm_kcalloc(dev, count, sizeof(struct scpi_chan),
if (!scpi_chan) GFP_KERNEL);
if (!scpi_info->channels)
return -ENOMEM; return -ENOMEM;
for (idx = 0; idx < count; idx++) { ret = devm_add_action(dev, scpi_free_channels, scpi_info);
if (ret)
return ret;
for (; scpi_info->num_chans < count; scpi_info->num_chans++) {
resource_size_t size; resource_size_t size;
struct scpi_chan *pchan = scpi_chan + idx; int idx = scpi_info->num_chans;
struct scpi_chan *pchan = scpi_info->channels + idx;
struct mbox_client *cl = &pchan->cl; struct mbox_client *cl = &pchan->cl;
struct device_node *shmem = of_parse_phandle(np, "shmem", idx); struct device_node *shmem = of_parse_phandle(np, "shmem", idx);
...@@ -983,15 +948,14 @@ static int scpi_probe(struct platform_device *pdev) ...@@ -983,15 +948,14 @@ static int scpi_probe(struct platform_device *pdev)
of_node_put(shmem); of_node_put(shmem);
if (ret) { if (ret) {
dev_err(dev, "failed to get SCPI payload mem resource\n"); dev_err(dev, "failed to get SCPI payload mem resource\n");
goto err; return ret;
} }
size = resource_size(&res); size = resource_size(&res);
pchan->rx_payload = devm_ioremap(dev, res.start, size); pchan->rx_payload = devm_ioremap(dev, res.start, size);
if (!pchan->rx_payload) { if (!pchan->rx_payload) {
dev_err(dev, "failed to ioremap SCPI payload\n"); dev_err(dev, "failed to ioremap SCPI payload\n");
ret = -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
goto err;
} }
pchan->tx_payload = pchan->rx_payload + (size >> 1); pchan->tx_payload = pchan->rx_payload + (size >> 1);
...@@ -1017,14 +981,9 @@ static int scpi_probe(struct platform_device *pdev) ...@@ -1017,14 +981,9 @@ static int scpi_probe(struct platform_device *pdev)
dev_err(dev, "failed to get channel%d err %d\n", dev_err(dev, "failed to get channel%d err %d\n",
idx, ret); idx, ret);
} }
err:
scpi_free_channels(dev, scpi_chan, idx);
scpi_info = NULL;
return ret; return ret;
} }
scpi_info->channels = scpi_chan;
scpi_info->num_chans = count;
scpi_info->commands = scpi_std_commands; scpi_info->commands = scpi_std_commands;
platform_set_drvdata(pdev, scpi_info); platform_set_drvdata(pdev, scpi_info);
...@@ -1043,23 +1002,31 @@ static int scpi_probe(struct platform_device *pdev) ...@@ -1043,23 +1002,31 @@ static int scpi_probe(struct platform_device *pdev)
ret = scpi_init_versions(scpi_info); ret = scpi_init_versions(scpi_info);
if (ret) { if (ret) {
dev_err(dev, "incorrect or no SCP firmware found\n"); dev_err(dev, "incorrect or no SCP firmware found\n");
scpi_remove(pdev);
return ret; return ret;
} }
_dev_info(dev, "SCP Protocol %d.%d Firmware %d.%d.%d version\n", if (scpi_info->is_legacy && !scpi_info->protocol_version &&
PROTOCOL_REV_MAJOR(scpi_info->protocol_version), !scpi_info->firmware_version)
PROTOCOL_REV_MINOR(scpi_info->protocol_version), dev_info(dev, "SCP Protocol legacy pre-1.0 firmware\n");
FW_REV_MAJOR(scpi_info->firmware_version), else
FW_REV_MINOR(scpi_info->firmware_version), dev_info(dev, "SCP Protocol %lu.%lu Firmware %lu.%lu.%lu version\n",
FW_REV_PATCH(scpi_info->firmware_version)); FIELD_GET(PROTO_REV_MAJOR_MASK,
scpi_info->protocol_version),
FIELD_GET(PROTO_REV_MINOR_MASK,
scpi_info->protocol_version),
FIELD_GET(FW_REV_MAJOR_MASK,
scpi_info->firmware_version),
FIELD_GET(FW_REV_MINOR_MASK,
scpi_info->firmware_version),
FIELD_GET(FW_REV_PATCH_MASK,
scpi_info->firmware_version));
scpi_info->scpi_ops = &scpi_ops; scpi_info->scpi_ops = &scpi_ops;
ret = sysfs_create_groups(&dev->kobj, versions_groups); ret = devm_device_add_groups(dev, versions_groups);
if (ret) if (ret)
dev_err(dev, "unable to create sysfs version group\n"); dev_err(dev, "unable to create sysfs version group\n");
return of_platform_populate(dev->of_node, NULL, NULL, dev); return devm_of_platform_populate(dev);
} }
static const struct of_device_id scpi_of_match[] = { static const struct of_device_id scpi_of_match[] = {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册