diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/firmware/ti_sci.c | 291 | ||||
-rw-r--r-- | drivers/firmware/ti_sci.h | 50 | ||||
-rw-r--r-- | drivers/mmc/am654_sdhci.c | 114 | ||||
-rw-r--r-- | drivers/power/domain/ti-sci-power-domain.c | 31 | ||||
-rw-r--r-- | drivers/remoteproc/Kconfig | 20 | ||||
-rw-r--r-- | drivers/remoteproc/Makefile | 2 | ||||
-rw-r--r-- | drivers/remoteproc/ti_k3_arm64_rproc.c (renamed from drivers/remoteproc/k3_rproc.c) | 136 | ||||
-rw-r--r-- | drivers/remoteproc/ti_sci_proc.h | 121 |
8 files changed, 626 insertions, 139 deletions
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 303aa6a631..1fd29f2cdf 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -87,11 +87,18 @@ struct ti_sci_info { struct mbox_chan chan_notify; struct ti_sci_xfer xfer; struct list_head list; + struct list_head dev_list; bool is_secure; u8 host_id; u8 seq; }; +struct ti_sci_exclusive_dev { + u32 id; + u32 count; + struct list_head list; +}; + #define handle_to_ti_sci_info(h) container_of(h, struct ti_sci_info, handle) /** @@ -101,7 +108,8 @@ struct ti_sci_info { * @msg_flags: Flag to set for the message * @buf: Buffer to be send to mailbox channel * @tx_message_size: transmit message size - * @rx_message_size: receive message size + * @rx_message_size: receive message size. may be set to zero for send-only + * transactions. * * Helper function which is used by various command functions that are * exposed to clients of this driver for allocating a message traffic event. @@ -121,7 +129,8 @@ static struct ti_sci_xfer *ti_sci_setup_one_xfer(struct ti_sci_info *info, /* Ensure we have sane transfer sizes */ if (rx_message_size > info->desc->max_msg_size || tx_message_size > info->desc->max_msg_size || - rx_message_size < sizeof(*hdr) || tx_message_size < sizeof(*hdr)) + (rx_message_size > 0 && rx_message_size < sizeof(*hdr)) || + tx_message_size < sizeof(*hdr)) return ERR_PTR(-ERANGE); info->seq = ~info->seq; @@ -219,7 +228,9 @@ static inline int ti_sci_do_xfer(struct ti_sci_info *info, xfer->tx_message.buf = (u32 *)secure_buf; xfer->tx_message.len += sizeof(secure_hdr); - xfer->rx_len += sizeof(secure_hdr); + + if (xfer->rx_len) + xfer->rx_len += sizeof(secure_hdr); } /* Send the message */ @@ -230,7 +241,11 @@ static inline int ti_sci_do_xfer(struct ti_sci_info *info, return ret; } - return ti_sci_get_response(info, xfer, &info->chan_rx); + /* Get response if requested */ + if (xfer->rx_len) + ret = ti_sci_get_response(info, xfer, &info->chan_rx); + + return ret; } /** @@ -419,6 +434,47 @@ static int ti_sci_cmd_set_board_config_pm(const struct ti_sci_handle *handle, addr, size); } +static struct ti_sci_exclusive_dev +*ti_sci_get_exclusive_dev(struct list_head *dev_list, u32 id) +{ + struct ti_sci_exclusive_dev *dev; + + list_for_each_entry(dev, dev_list, list) + if (dev->id == id) + return dev; + + return NULL; +} + +static void ti_sci_add_exclusive_dev(struct ti_sci_info *info, u32 id) +{ + struct ti_sci_exclusive_dev *dev; + + dev = ti_sci_get_exclusive_dev(&info->dev_list, id); + if (dev) { + dev->count++; + return; + } + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + dev->id = id; + dev->count = 1; + INIT_LIST_HEAD(&dev->list); + list_add_tail(&dev->list, &info->dev_list); +} + +static void ti_sci_delete_exclusive_dev(struct ti_sci_info *info, u32 id) +{ + struct ti_sci_exclusive_dev *dev; + + dev = ti_sci_get_exclusive_dev(&info->dev_list, id); + if (!dev) + return; + + if (dev->count > 0) + dev->count--; +} + /** * ti_sci_set_device_state() - Set device state helper * @handle: pointer to TI SCI handle @@ -466,6 +522,54 @@ static int ti_sci_set_device_state(const struct ti_sci_handle *handle, if (!ti_sci_is_response_ack(resp)) return -ENODEV; + if (state == MSG_DEVICE_SW_STATE_AUTO_OFF) + ti_sci_delete_exclusive_dev(info, id); + else if (flags & MSG_FLAG_DEVICE_EXCLUSIVE) + ti_sci_add_exclusive_dev(info, id); + + return ret; +} + +/** + * ti_sci_set_device_state_no_wait() - Set device state helper without + * requesting or waiting for a response. + * @handle: pointer to TI SCI handle + * @id: Device identifier + * @flags: flags to setup for the device + * @state: State to move the device to + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_set_device_state_no_wait(const struct ti_sci_handle *handle, + u32 id, u32 flags, u8 state) +{ + struct ti_sci_msg_req_set_device_state req; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_DEVICE_STATE, + flags | TI_SCI_FLAG_REQ_GENERIC_NORESPONSE, + (u32 *)&req, sizeof(req), 0); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.id = id; + req.state = state; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) + dev_err(info->dev, "Mbox send fail %d\n", ret); + return ret; } @@ -547,8 +651,14 @@ static int ti_sci_get_device_state(const struct ti_sci_handle *handle, */ static int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id) { - return ti_sci_set_device_state(handle, id, - MSG_FLAG_DEVICE_EXCLUSIVE, + return ti_sci_set_device_state(handle, id, 0, + MSG_DEVICE_SW_STATE_ON); +} + +static int ti_sci_cmd_get_device_exclusive(const struct ti_sci_handle *handle, + u32 id) +{ + return ti_sci_set_device_state(handle, id, MSG_FLAG_DEVICE_EXCLUSIVE, MSG_DEVICE_SW_STATE_ON); } @@ -566,7 +676,14 @@ static int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id) static int ti_sci_cmd_idle_device(const struct ti_sci_handle *handle, u32 id) { return ti_sci_set_device_state(handle, id, - MSG_FLAG_DEVICE_EXCLUSIVE, + 0, + MSG_DEVICE_SW_STATE_RETENTION); +} + +static int ti_sci_cmd_idle_device_exclusive(const struct ti_sci_handle *handle, + u32 id) +{ + return ti_sci_set_device_state(handle, id, MSG_FLAG_DEVICE_EXCLUSIVE, MSG_DEVICE_SW_STATE_RETENTION); } @@ -583,8 +700,27 @@ static int ti_sci_cmd_idle_device(const struct ti_sci_handle *handle, u32 id) */ static int ti_sci_cmd_put_device(const struct ti_sci_handle *handle, u32 id) { - return ti_sci_set_device_state(handle, id, - 0, MSG_DEVICE_SW_STATE_AUTO_OFF); + return ti_sci_set_device_state(handle, id, 0, + MSG_DEVICE_SW_STATE_AUTO_OFF); +} + +static +int ti_sci_cmd_release_exclusive_devices(const struct ti_sci_handle *handle) +{ + struct ti_sci_exclusive_dev *dev, *tmp; + struct ti_sci_info *info; + int i, cnt; + + info = handle_to_ti_sci_info(handle); + + list_for_each_entry_safe(dev, tmp, &info->dev_list, list) { + cnt = dev->count; + debug("%s: id = %d, cnt = %d\n", __func__, dev->id, cnt); + for (i = 0; i < cnt; i++) + ti_sci_cmd_put_device(handle, dev->id); + } + + return 0; } /** @@ -2027,6 +2163,137 @@ static int ti_sci_cmd_get_proc_boot_status(const struct ti_sci_handle *handle, } /** + * ti_sci_proc_wait_boot_status_no_wait() - Helper function to wait for a + * processor boot status without requesting or + * waiting for a response. + * @proc_id: Processor ID this request is for + * @num_wait_iterations: Total number of iterations we will check before + * we will timeout and give up + * @num_match_iterations: How many iterations should we have continued + * status to account for status bits glitching. + * This is to make sure that match occurs for + * consecutive checks. This implies that the + * worst case should consider that the stable + * time should at the worst be num_wait_iterations + * num_match_iterations to prevent timeout. + * @delay_per_iteration_us: Specifies how long to wait (in micro seconds) + * between each status checks. This is the minimum + * duration, and overhead of register reads and + * checks are on top of this and can vary based on + * varied conditions. + * @delay_before_iterations_us: Specifies how long to wait (in micro seconds) + * before the very first check in the first + * iteration of status check loop. This is the + * minimum duration, and overhead of register + * reads and checks are. + * @status_flags_1_set_all_wait:If non-zero, Specifies that all bits of the + * status matching this field requested MUST be 1. + * @status_flags_1_set_any_wait:If non-zero, Specifies that at least one of the + * bits matching this field requested MUST be 1. + * @status_flags_1_clr_all_wait:If non-zero, Specifies that all bits of the + * status matching this field requested MUST be 0. + * @status_flags_1_clr_any_wait:If non-zero, Specifies that at least one of the + * bits matching this field requested MUST be 0. + * + * Return: 0 if all goes well, else appropriate error message + */ +static int +ti_sci_proc_wait_boot_status_no_wait(const struct ti_sci_handle *handle, + u8 proc_id, + u8 num_wait_iterations, + u8 num_match_iterations, + u8 delay_per_iteration_us, + u8 delay_before_iterations_us, + u32 status_flags_1_set_all_wait, + u32 status_flags_1_set_any_wait, + u32 status_flags_1_clr_all_wait, + u32 status_flags_1_clr_any_wait) +{ + struct ti_sci_msg_req_wait_proc_boot_status req; + struct ti_sci_info *info; + struct ti_sci_xfer *xfer; + int ret = 0; + + if (IS_ERR(handle)) + return PTR_ERR(handle); + if (!handle) + return -EINVAL; + + info = handle_to_ti_sci_info(handle); + + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_WAIT_PROC_BOOT_STATUS, + TI_SCI_FLAG_REQ_GENERIC_NORESPONSE, + (u32 *)&req, sizeof(req), 0); + if (IS_ERR(xfer)) { + ret = PTR_ERR(xfer); + dev_err(info->dev, "Message alloc failed(%d)\n", ret); + return ret; + } + req.processor_id = proc_id; + req.num_wait_iterations = num_wait_iterations; + req.num_match_iterations = num_match_iterations; + req.delay_per_iteration_us = delay_per_iteration_us; + req.delay_before_iterations_us = delay_before_iterations_us; + req.status_flags_1_set_all_wait = status_flags_1_set_all_wait; + req.status_flags_1_set_any_wait = status_flags_1_set_any_wait; + req.status_flags_1_clr_all_wait = status_flags_1_clr_all_wait; + req.status_flags_1_clr_any_wait = status_flags_1_clr_any_wait; + + ret = ti_sci_do_xfer(info, xfer); + if (ret) + dev_err(info->dev, "Mbox send fail %d\n", ret); + + return ret; +} + +/** + * ti_sci_cmd_proc_shutdown_no_wait() - Command to shutdown a core without + * requesting or waiting for a response. Note that this API call + * should be followed by placing the respective processor into + * either WFE or WFI mode. + * @handle: Pointer to TI SCI handle + * @proc_id: Processor ID this request is for + * + * Return: 0 if all went well, else returns appropriate error value. + */ +static int ti_sci_cmd_proc_shutdown_no_wait(const struct ti_sci_handle *handle, + u8 proc_id) +{ + int ret; + + /* + * Send the core boot status wait message waiting for either WFE or + * WFI without requesting or waiting for a TISCI response with the + * maximum wait time to give us the best chance to get to the WFE/WFI + * command that should follow the invocation of this API before the + * DMSC-internal processing of this command times out. Note that + * waiting for the R5 WFE/WFI flags will also work on an ARMV8 type + * core as the related flag bit positions are the same. + */ + ret = ti_sci_proc_wait_boot_status_no_wait(handle, proc_id, + U8_MAX, 100, U8_MAX, U8_MAX, + 0, PROC_BOOT_STATUS_FLAG_R5_WFE | PROC_BOOT_STATUS_FLAG_R5_WFI, + 0, 0); + if (ret) { + dev_err(info->dev, "Sending core %u wait message fail %d\n", + proc_id, ret); + return ret; + } + + /* + * Release a processor managed by TISCI without requesting or waiting + * for a response. + */ + ret = ti_sci_set_device_state_no_wait(handle, proc_id, 0, + MSG_DEVICE_SW_STATE_AUTO_OFF); + if (ret) + dev_err(info->dev, "Sending core %u shutdown message fail %d\n", + proc_id, ret); + + return ret; +} + +/** * ti_sci_cmd_ring_config() - configure RA ring * @handle: pointer to TI SCI handle * @valid_params: Bitfield defining validity of ring configuration parameters. @@ -2632,7 +2899,9 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) bops->board_config_pm = ti_sci_cmd_set_board_config_pm; dops->get_device = ti_sci_cmd_get_device; + dops->get_device_exclusive = ti_sci_cmd_get_device_exclusive; dops->idle_device = ti_sci_cmd_idle_device; + dops->idle_device_exclusive = ti_sci_cmd_idle_device_exclusive; dops->put_device = ti_sci_cmd_put_device; dops->is_valid = ti_sci_cmd_dev_is_valid; dops->get_context_loss_count = ti_sci_cmd_dev_get_clcnt; @@ -2642,6 +2911,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) dops->is_transitioning = ti_sci_cmd_dev_is_trans; dops->set_device_resets = ti_sci_cmd_set_device_resets; dops->get_device_resets = ti_sci_cmd_get_device_resets; + dops->release_exclusive_devices = ti_sci_cmd_release_exclusive_devices; cops->get_clock = ti_sci_cmd_get_clock; cops->idle_clock = ti_sci_cmd_idle_clock; @@ -2672,6 +2942,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info) pops->set_proc_boot_ctrl = ti_sci_cmd_set_proc_boot_ctrl; pops->proc_auth_boot_image = ti_sci_cmd_proc_auth_boot_image; pops->get_proc_boot_status = ti_sci_cmd_get_proc_boot_status; + pops->proc_shutdown_no_wait = ti_sci_cmd_proc_shutdown_no_wait; rops->config = ti_sci_cmd_ring_config; rops->get_config = ti_sci_cmd_ring_get_config; @@ -2835,6 +3106,8 @@ static int ti_sci_probe(struct udevice *dev) ret = ti_sci_cmd_get_revision(&info->handle); + INIT_LIST_HEAD(&info->dev_list); + return ret; } diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index a484b1fa40..69ff74d6a9 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h @@ -50,6 +50,7 @@ #define TISCI_MSG_SET_PROC_BOOT_CTRL 0xc101 #define TISCI_MSG_PROC_AUTH_BOOT_IMIAGE 0xc120 #define TISCI_MSG_GET_PROC_BOOT_STATUS 0xc400 +#define TISCI_MSG_WAIT_PROC_BOOT_STATUS 0xc401 /* Resource Management Requests */ #define TI_SCI_MSG_GET_RESOURCE_RANGE 0x1500 @@ -773,6 +774,55 @@ struct ti_sci_msg_resp_get_proc_boot_status { } __packed; /** + * struct ti_sci_msg_req_wait_proc_boot_status - Wait for a processor + * boot status + * @hdr: Generic Header + * @processor_id: ID of processor + * @num_wait_iterations: Total number of iterations we will check before + * we will timeout and give up + * @num_match_iterations: How many iterations should we have continued + * status to account for status bits glitching. + * This is to make sure that match occurs for + * consecutive checks. This implies that the + * worst case should consider that the stable + * time should at the worst be num_wait_iterations + * num_match_iterations to prevent timeout. + * @delay_per_iteration_us: Specifies how long to wait (in micro seconds) + * between each status checks. This is the minimum + * duration, and overhead of register reads and + * checks are on top of this and can vary based on + * varied conditions. + * @delay_before_iterations_us: Specifies how long to wait (in micro seconds) + * before the very first check in the first + * iteration of status check loop. This is the + * minimum duration, and overhead of register + * reads and checks are. + * @status_flags_1_set_all_wait:If non-zero, Specifies that all bits of the + * status matching this field requested MUST be 1. + * @status_flags_1_set_any_wait:If non-zero, Specifies that at least one of the + * bits matching this field requested MUST be 1. + * @status_flags_1_clr_all_wait:If non-zero, Specifies that all bits of the + * status matching this field requested MUST be 0. + * @status_flags_1_clr_any_wait:If non-zero, Specifies that at least one of the + * bits matching this field requested MUST be 0. + * + * Request type is TISCI_MSG_WAIT_PROC_BOOT_STATUS, response is appropriate + * message, or NACK in case of inability to satisfy request. + */ +struct ti_sci_msg_req_wait_proc_boot_status { + struct ti_sci_msg_hdr hdr; + u8 processor_id; + u8 num_wait_iterations; + u8 num_match_iterations; + u8 delay_per_iteration_us; + u8 delay_before_iterations_us; + u32 status_flags_1_set_all_wait; + u32 status_flags_1_set_any_wait; + u32 status_flags_1_clr_all_wait; + u32 status_flags_1_clr_any_wait; +} __packed; + +/** * struct ti_sci_msg_rm_ring_cfg_req - Configure a Navigator Subsystem ring * * Configures the non-real-time registers of a Navigator Subsystem ring. diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c index fb0fb58070..1793a3f99a 100644 --- a/drivers/mmc/am654_sdhci.c +++ b/drivers/mmc/am654_sdhci.c @@ -72,6 +72,8 @@ struct am654_sdhci_plat { u32 otap_del_sel; u32 trm_icp; u32 drv_strength; + u32 flags; +#define DLL_PRESENT (1 << 0) bool dll_on; }; @@ -162,6 +164,10 @@ const struct sdhci_ops am654_sdhci_ops = { .set_control_reg = &am654_sdhci_set_control_reg, }; +const struct sdhci_ops j721e_4bit_sdhci_ops = { + .set_control_reg = &am654_sdhci_set_control_reg, +}; + int am654_sdhci_init(struct am654_sdhci_plat *plat) { u32 ctl_cfg_2 = 0; @@ -172,24 +178,28 @@ int am654_sdhci_init(struct am654_sdhci_plat *plat) mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; regmap_update_bits(plat->base, PHY_CTRL4, mask, 0x0); - regmap_read(plat->base, PHY_STAT1, &val); - if (~val & CALDONE_MASK) { - /* Calibrate IO lines */ - regmap_update_bits(plat->base, PHY_CTRL1, PDB_MASK, PDB_MASK); - ret = regmap_read_poll_timeout(plat->base, PHY_STAT1, val, - val & CALDONE_MASK, 1, 20); - if (ret) - return ret; - } + if (plat->flags & DLL_PRESENT) { + regmap_read(plat->base, PHY_STAT1, &val); + if (~val & CALDONE_MASK) { + /* Calibrate IO lines */ + regmap_update_bits(plat->base, PHY_CTRL1, PDB_MASK, + PDB_MASK); + ret = regmap_read_poll_timeout(plat->base, PHY_STAT1, + val, val & CALDONE_MASK, + 1, 20); + if (ret) + return ret; + } - /* Configure DLL TRIM */ - mask = DLL_TRIM_ICP_MASK; - val = plat->trm_icp << DLL_TRIM_ICP_SHIFT; + /* Configure DLL TRIM */ + mask = DLL_TRIM_ICP_MASK; + val = plat->trm_icp << DLL_TRIM_ICP_SHIFT; - /* Configure DLL driver strength */ - mask |= DR_TY_MASK; - val |= plat->drv_strength << DR_TY_SHIFT; - regmap_update_bits(plat->base, PHY_CTRL1, mask, val); + /* Configure DLL driver strength */ + mask |= DR_TY_MASK; + val |= plat->drv_strength << DR_TY_SHIFT; + regmap_update_bits(plat->base, PHY_CTRL1, mask, val); + } /* Enable pins by setting IO mux to 0 */ regmap_update_bits(plat->base, PHY_CTRL1, IOMUX_ENABLE_MASK, 0); @@ -245,7 +255,7 @@ static int am654_sdhci_probe(struct udevice *dev) AM654_SDHCI_MIN_FREQ); if (ret) return ret; - host->ops = &am654_sdhci_ops; + host->ops = (struct sdhci_ops *)dev_get_driver_data(dev); host->mmc->priv = host; upriv->mmc = host->mmc; @@ -268,37 +278,44 @@ static int am654_sdhci_ofdata_to_platdata(struct udevice *dev) host->ioaddr = (void *)dev_read_addr(dev); plat->non_removable = dev_read_bool(dev, "non-removable"); - ret = dev_read_u32(dev, "ti,trm-icp", &plat->trm_icp); - if (ret) - return ret; + if (device_is_compatible(dev, "ti,am654-sdhci-5.1") || + device_is_compatible(dev, "ti,j721e-sdhci-8bit")) + plat->flags |= DLL_PRESENT; ret = dev_read_u32(dev, "ti,otap-del-sel", &plat->otap_del_sel); if (ret) return ret; - ret = dev_read_u32(dev, "ti,driver-strength-ohm", &drv_strength); - if (ret) - return ret; + if (plat->flags & DLL_PRESENT) { + ret = dev_read_u32(dev, "ti,trm-icp", &plat->trm_icp); + if (ret) + return ret; + + ret = dev_read_u32(dev, "ti,driver-strength-ohm", + &drv_strength); + if (ret) + return ret; - switch (drv_strength) { - case 50: - plat->drv_strength = DRIVER_STRENGTH_50_OHM; - break; - case 33: - plat->drv_strength = DRIVER_STRENGTH_33_OHM; - break; - case 66: - plat->drv_strength = DRIVER_STRENGTH_66_OHM; - break; - case 100: - plat->drv_strength = DRIVER_STRENGTH_100_OHM; - break; - case 40: - plat->drv_strength = DRIVER_STRENGTH_40_OHM; - break; - default: - dev_err(dev, "Invalid driver strength\n"); - return -EINVAL; + switch (drv_strength) { + case 50: + plat->drv_strength = DRIVER_STRENGTH_50_OHM; + break; + case 33: + plat->drv_strength = DRIVER_STRENGTH_33_OHM; + break; + case 66: + plat->drv_strength = DRIVER_STRENGTH_66_OHM; + break; + case 100: + plat->drv_strength = DRIVER_STRENGTH_100_OHM; + break; + case 40: + plat->drv_strength = DRIVER_STRENGTH_40_OHM; + break; + default: + dev_err(dev, "Invalid driver strength\n"); + return -EINVAL; + } } ret = mmc_of_parse(dev, cfg); @@ -316,7 +333,18 @@ static int am654_sdhci_bind(struct udevice *dev) } static const struct udevice_id am654_sdhci_ids[] = { - { .compatible = "ti,am654-sdhci-5.1" }, + { + .compatible = "ti,am654-sdhci-5.1", + .data = (ulong)&am654_sdhci_ops, + }, + { + .compatible = "ti,j721e-sdhci-8bit", + .data = (ulong)&am654_sdhci_ops, + }, + { + .compatible = "ti,j721e-sdhci-4bit", + .data = (ulong)&j721e_4bit_sdhci_ops, + }, { } }; diff --git a/drivers/power/domain/ti-sci-power-domain.c b/drivers/power/domain/ti-sci-power-domain.c index aafde62cbf..b9cd37b612 100644 --- a/drivers/power/domain/ti-sci-power-domain.c +++ b/drivers/power/domain/ti-sci-power-domain.c @@ -13,6 +13,7 @@ #include <errno.h> #include <power-domain-uclass.h> #include <linux/soc/ti/ti_sci_protocol.h> +#include <dt-bindings/soc/ti,sci_pm_domain.h> /** * struct ti_sci_power_domain_data - pm domain controller information structure @@ -56,11 +57,16 @@ static int ti_sci_power_domain_on(struct power_domain *pd) struct ti_sci_power_domain_data *data = dev_get_priv(pd->dev); const struct ti_sci_handle *sci = data->sci; const struct ti_sci_dev_ops *dops = &sci->ops.dev_ops; + u8 flags = (uintptr_t)pd->priv; int ret; debug("%s(pd=%p)\n", __func__, pd); - ret = dops->get_device(sci, pd->id); + if (flags & TI_SCI_PD_EXCLUSIVE) + ret = dops->get_device_exclusive(sci, pd->id); + else + ret = dops->get_device(sci, pd->id); + if (ret) dev_err(power_domain->dev, "%s: get_device failed (%d)\n", __func__, ret); @@ -85,6 +91,28 @@ static int ti_sci_power_domain_off(struct power_domain *pd) return ret; } +static int ti_sci_power_domain_of_xlate(struct power_domain *pd, + struct ofnode_phandle_args *args) +{ + u8 flags; + + debug("%s(power_domain=%p)\n", __func__, pd); + + if (args->args_count < 1) { + debug("Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + pd->id = args->args[0]; + /* By default request for device exclusive */ + flags = TI_SCI_PD_EXCLUSIVE; + if (args->args_count == 2) + flags = args->args[1] & TI_SCI_PD_EXCLUSIVE; + pd->priv = (void *)(uintptr_t)flags; + + return 0; +} + static const struct udevice_id ti_sci_power_domain_of_match[] = { { .compatible = "ti,sci-pm-domain" }, { /* sentinel */ } @@ -95,6 +123,7 @@ static struct power_domain_ops ti_sci_power_domain_ops = { .free = ti_sci_power_domain_free, .on = ti_sci_power_domain_on, .off = ti_sci_power_domain_off, + .of_xlate = ti_sci_power_domain_of_xlate, }; U_BOOT_DRIVER(ti_sci_pm_domains) = { diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index fa6f1113e1..f54a245424 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -22,15 +22,6 @@ config K3_SYSTEM_CONTROLLER help Say 'y' here to add support for TI' K3 System Controller. -config REMOTEPROC_K3 - bool "Support for TI's K3 based remoteproc driver" - select REMOTEPROC - depends on DM - depends on ARCH_K3 - depends on OF_CONTROL - help - Say 'y' here to add support for TI' K3 remoteproc driver. - config REMOTEPROC_SANDBOX bool "Support for Test processor for Sandbox" select REMOTEPROC @@ -50,6 +41,17 @@ config REMOTEPROC_STM32_COPRO Say 'y' here to add support for STM32 Cortex-M4 coprocessors via the remoteproc framework. +config REMOTEPROC_TI_K3_ARM64 + bool "Support for TI's K3 based ARM64 remoteproc driver" + select REMOTEPROC + depends on DM + depends on ARCH_K3 + depends on OF_CONTROL + help + Say y here to support TI's ARM64 processor subsystems + on various TI K3 family of SoCs through the remote processor + framework. + config REMOTEPROC_TI_POWER bool "Support for TI Power processor" select REMOTEPROC diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index b9a06acdef..271ba55b09 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -8,7 +8,7 @@ obj-$(CONFIG_$(SPL_)REMOTEPROC) += rproc-uclass.o rproc-elf-loader.o # Remote proc drivers - Please keep this list alphabetically sorted. obj-$(CONFIG_K3_SYSTEM_CONTROLLER) += k3_system_controller.o -obj-$(CONFIG_REMOTEPROC_K3) += k3_rproc.o obj-$(CONFIG_REMOTEPROC_SANDBOX) += sandbox_testproc.o obj-$(CONFIG_REMOTEPROC_STM32_COPRO) += stm32_copro.o +obj-$(CONFIG_REMOTEPROC_TI_K3_ARM64) += ti_k3_arm64_rproc.o obj-$(CONFIG_REMOTEPROC_TI_POWER) += ti_power_proc.o diff --git a/drivers/remoteproc/k3_rproc.c b/drivers/remoteproc/ti_k3_arm64_rproc.c index 3c29d925ce..9676a96f98 100644 --- a/drivers/remoteproc/k3_rproc.c +++ b/drivers/remoteproc/ti_k3_arm64_rproc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Texas Instruments' K3 Remoteproc driver + * Texas Instruments' K3 ARM64 Remoteproc driver * * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ * Lokesh Vutla <lokeshvutla@ti.com> @@ -16,6 +16,7 @@ #include <asm/io.h> #include <power-domain.h> #include <linux/soc/ti/ti_sci_protocol.h> +#include "ti_sci_proc.h" #define INVALID_ID 0xffff @@ -23,68 +24,53 @@ #define GTC_CNTR_EN 0x3 /** - * struct k3_rproc_privdata - Structure representing Remote processor data. + * struct k3_arm64_privdata - Structure representing Remote processor data. * @rproc_pwrdmn: rproc power domain data * @rproc_rst: rproc reset control data * @sci: Pointer to TISCI handle + * @tsp: TISCI processor control helper structure * @gtc_base: Timer base address. - * @proc_id: TISCI processor ID - * @host_id: TISCI host id to which the processor gets assigned to. */ -struct k3_rproc_privdata { +struct k3_arm64_privdata { struct power_domain rproc_pwrdmn; struct power_domain gtc_pwrdmn; struct reset_ctl rproc_rst; - const struct ti_sci_handle *sci; + struct ti_sci_proc tsp; void *gtc_base; - u16 proc_id; - u16 host_id; }; /** - * k3_rproc_load() - Load up the Remote processor image + * k3_arm64_load() - Load up the Remote processor image * @dev: rproc device pointer * @addr: Address at which image is available * @size: size of the image * * Return: 0 if all goes good, else appropriate error message. */ -static int k3_rproc_load(struct udevice *dev, ulong addr, ulong size) +static int k3_arm64_load(struct udevice *dev, ulong addr, ulong size) { - struct k3_rproc_privdata *rproc = dev_get_priv(dev); - const struct ti_sci_proc_ops *pops = &rproc->sci->ops.proc_ops; + struct k3_arm64_privdata *rproc = dev_get_priv(dev); int ret; dev_dbg(dev, "%s addr = 0x%lx, size = 0x%lx\n", __func__, addr, size); /* request for the processor */ - ret = pops->proc_request(rproc->sci, rproc->proc_id); - if (ret) { - dev_err(dev, "Requesting processor failed %d\n", ret); + ret = ti_sci_proc_request(&rproc->tsp); + if (ret) return ret; - } - - ret = pops->set_proc_boot_cfg(rproc->sci, rproc->proc_id, addr, 0, 0); - if (ret) { - dev_err(dev, "set_proc_boot_cfg failed %d\n", ret); - return ret; - } - - dev_dbg(dev, "%s: rproc successfully loaded\n", __func__); - return 0; + return ti_sci_proc_set_config(&rproc->tsp, addr, 0, 0); } /** - * k3_rproc_start() - Start the remote processor + * k3_arm64_start() - Start the remote processor * @dev: rproc device pointer * * Return: 0 if all went ok, else return appropriate error */ -static int k3_rproc_start(struct udevice *dev) +static int k3_arm64_start(struct udevice *dev) { - struct k3_rproc_privdata *rproc = dev_get_priv(dev); - const struct ti_sci_proc_ops *pops = &rproc->sci->ops.proc_ops; + struct k3_arm64_privdata *rproc = dev_get_priv(dev); int ret; dev_dbg(dev, "%s\n", __func__); @@ -109,33 +95,16 @@ static int k3_rproc_start(struct udevice *dev) return ret; } - if (rproc->host_id != INVALID_ID) { - ret = pops->proc_handover(rproc->sci, rproc->proc_id, - rproc->host_id); - if (ret) { - dev_err(dev, "Handover processor failed %d\n", ret); - return ret; - } - } else { - ret = pops->proc_release(rproc->sci, rproc->proc_id); - if (ret) { - dev_err(dev, "Processor release failed %d\n", ret); - return ret; - } - } - - dev_dbg(dev, "%s: rproc successfully started\n", __func__); - - return 0; + return ti_sci_proc_release(&rproc->tsp); } /** - * k3_rproc_init() - Initialize the remote processor + * k3_arm64_init() - Initialize the remote processor * @dev: rproc device pointer * * Return: 0 if all went ok, else return appropriate error */ -static int k3_rproc_init(struct udevice *dev) +static int k3_arm64_init(struct udevice *dev) { dev_dbg(dev, "%s\n", __func__); @@ -145,12 +114,33 @@ static int k3_rproc_init(struct udevice *dev) return 0; } -static const struct dm_rproc_ops k3_rproc_ops = { - .init = k3_rproc_init, - .load = k3_rproc_load, - .start = k3_rproc_start, +static const struct dm_rproc_ops k3_arm64_ops = { + .init = k3_arm64_init, + .load = k3_arm64_load, + .start = k3_arm64_start, }; +static int ti_sci_proc_of_to_priv(struct udevice *dev, struct ti_sci_proc *tsp) +{ + dev_dbg(dev, "%s\n", __func__); + + tsp->sci = ti_sci_get_by_phandle(dev, "ti,sci"); + if (IS_ERR(tsp->sci)) { + dev_err(dev, "ti_sci get failed: %ld\n", PTR_ERR(tsp->sci)); + return PTR_ERR(tsp->sci); + } + + tsp->proc_id = dev_read_u32_default(dev, "ti,sci-proc-id", INVALID_ID); + if (tsp->proc_id == INVALID_ID) { + dev_err(dev, "proc id not populated\n"); + return -ENOENT; + } + tsp->host_id = dev_read_u32_default(dev, "ti,sci-host-id", INVALID_ID); + tsp->ops = &tsp->sci->ops.proc_ops; + + return 0; +} + /** * k3_of_to_priv() - generate private data from device tree * @dev: corresponding k3 remote processor device @@ -158,8 +148,8 @@ static const struct dm_rproc_ops k3_rproc_ops = { * * Return: 0 if all goes good, else appropriate error message. */ -static int k3_rproc_of_to_priv(struct udevice *dev, - struct k3_rproc_privdata *rproc) +static int k3_arm64_of_to_priv(struct udevice *dev, + struct k3_arm64_privdata *rproc) { int ret; @@ -183,11 +173,9 @@ static int k3_rproc_of_to_priv(struct udevice *dev, return ret; } - rproc->sci = ti_sci_get_by_phandle(dev, "ti,sci"); - if (IS_ERR(rproc->sci)) { - dev_err(dev, "ti_sci get failed: %d\n", ret); - return PTR_ERR(rproc->sci); - } + ret = ti_sci_proc_of_to_priv(dev, &rproc->tsp); + if (ret) + return ret; rproc->gtc_base = dev_read_addr_ptr(dev); if (!rproc->gtc_base) { @@ -195,30 +183,25 @@ static int k3_rproc_of_to_priv(struct udevice *dev, return -ENODEV; } - rproc->proc_id = dev_read_u32_default(dev, "ti,sci-proc-id", - INVALID_ID); - rproc->host_id = dev_read_u32_default(dev, "ti,sci-host-id", - INVALID_ID); - return 0; } /** - * k3_rproc_probe() - Basic probe + * k3_arm64_probe() - Basic probe * @dev: corresponding k3 remote processor device * * Return: 0 if all goes good, else appropriate error message. */ -static int k3_rproc_probe(struct udevice *dev) +static int k3_arm64_probe(struct udevice *dev) { - struct k3_rproc_privdata *priv; + struct k3_arm64_privdata *priv; int ret; dev_dbg(dev, "%s\n", __func__); priv = dev_get_priv(dev); - ret = k3_rproc_of_to_priv(dev, priv); + ret = k3_arm64_of_to_priv(dev, priv); if (ret) { dev_dbg(dev, "%s: Probe failed with error %d\n", __func__, ret); return ret; @@ -229,16 +212,17 @@ static int k3_rproc_probe(struct udevice *dev) return 0; } -static const struct udevice_id k3_rproc_ids[] = { +static const struct udevice_id k3_arm64_ids[] = { + { .compatible = "ti,am654-arm64"}, { .compatible = "ti,am654-rproc"}, {} }; -U_BOOT_DRIVER(k3_rproc) = { - .name = "k3_rproc", - .of_match = k3_rproc_ids, +U_BOOT_DRIVER(k3_arm64) = { + .name = "k3_arm64", + .of_match = k3_arm64_ids, .id = UCLASS_REMOTEPROC, - .ops = &k3_rproc_ops, - .probe = k3_rproc_probe, - .priv_auto_alloc_size = sizeof(struct k3_rproc_privdata), + .ops = &k3_arm64_ops, + .probe = k3_arm64_probe, + .priv_auto_alloc_size = sizeof(struct k3_arm64_privdata), }; diff --git a/drivers/remoteproc/ti_sci_proc.h b/drivers/remoteproc/ti_sci_proc.h new file mode 100644 index 0000000000..ccfc39ec88 --- /dev/null +++ b/drivers/remoteproc/ti_sci_proc.h @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Texas Instruments TI-SCI Processor Controller Helper Functions + * + * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/ + * Lokesh Vutla <lokeshvutla@ti.com> + * Suman Anna <s-anna@ti.com> + */ + +#ifndef REMOTEPROC_TI_SCI_PROC_H +#define REMOTEPROC_TI_SCI_PROC_H + +#define TISCI_INVALID_HOST 0xff + +/** + * struct ti_sci_proc - structure representing a processor control client + * @sci: cached TI-SCI protocol handle + * @ops: cached TI-SCI proc ops + * @proc_id: processor id for the consumer remoteproc device + * @host_id: host id to pass the control over for this consumer remoteproc + * device + */ +struct ti_sci_proc { + const struct ti_sci_handle *sci; + const struct ti_sci_proc_ops *ops; + u8 proc_id; + u8 host_id; +}; + +static inline int ti_sci_proc_request(struct ti_sci_proc *tsp) +{ + int ret; + + debug("%s: proc_id = %d\n", __func__, tsp->proc_id); + + ret = tsp->ops->proc_request(tsp->sci, tsp->proc_id); + if (ret) + pr_err("ti-sci processor request failed: %d\n", ret); + return ret; +} + +static inline int ti_sci_proc_release(struct ti_sci_proc *tsp) +{ + int ret; + + debug("%s: proc_id = %d\n", __func__, tsp->proc_id); + + if (tsp->host_id != TISCI_INVALID_HOST) + ret = tsp->ops->proc_handover(tsp->sci, tsp->proc_id, + tsp->host_id); + else + ret = tsp->ops->proc_release(tsp->sci, tsp->proc_id); + + if (ret) + pr_err("ti-sci processor release failed: %d\n", ret); + return ret; +} + +static inline int ti_sci_proc_handover(struct ti_sci_proc *tsp) +{ + int ret; + + debug("%s: proc_id = %d\n", __func__, tsp->proc_id); + + ret = tsp->ops->proc_handover(tsp->sci, tsp->proc_id, tsp->host_id); + if (ret) + pr_err("ti-sci processor handover of %d to %d failed: %d\n", + tsp->proc_id, tsp->host_id, ret); + return ret; +} + +static inline int ti_sci_proc_get_status(struct ti_sci_proc *tsp, + u64 *boot_vector, u32 *cfg_flags, + u32 *ctrl_flags, u32 *status_flags) +{ + int ret; + + ret = tsp->ops->get_proc_boot_status(tsp->sci, tsp->proc_id, + boot_vector, cfg_flags, ctrl_flags, + status_flags); + if (ret) + pr_err("ti-sci processor get_status failed: %d\n", ret); + + debug("%s: proc_id = %d, boot_vector = 0x%llx, cfg_flags = 0x%x, ctrl_flags = 0x%x, sts = 0x%x\n", + __func__, tsp->proc_id, *boot_vector, *cfg_flags, *ctrl_flags, + *status_flags); + return ret; +} + +static inline int ti_sci_proc_set_config(struct ti_sci_proc *tsp, + u64 boot_vector, + u32 cfg_set, u32 cfg_clr) +{ + int ret; + + debug("%s: proc_id = %d, boot_vector = 0x%llx, cfg_set = 0x%x, cfg_clr = 0x%x\n", + __func__, tsp->proc_id, boot_vector, cfg_set, cfg_clr); + + ret = tsp->ops->set_proc_boot_cfg(tsp->sci, tsp->proc_id, boot_vector, + cfg_set, cfg_clr); + if (ret) + pr_err("ti-sci processor set_config failed: %d\n", ret); + return ret; +} + +static inline int ti_sci_proc_set_control(struct ti_sci_proc *tsp, + u32 ctrl_set, u32 ctrl_clr) +{ + int ret; + + debug("%s: proc_id = %d, ctrl_set = 0x%x, ctrl_clr = 0x%x\n", __func__, + tsp->proc_id, ctrl_set, ctrl_clr); + + ret = tsp->ops->set_proc_boot_ctrl(tsp->sci, tsp->proc_id, ctrl_set, + ctrl_clr); + if (ret) + pr_err("ti-sci processor set_control failed: %d\n", ret); + return ret; +} + +#endif /* REMOTEPROC_TI_SCI_PROC_H */ |