2017-11-07 13:58:41 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2015-12-16 10:59:19 +00:00
|
|
|
/*
|
|
|
|
* Arche Platform driver to control APB.
|
|
|
|
*
|
|
|
|
* Copyright 2014-2015 Google Inc.
|
|
|
|
* Copyright 2014-2015 Linaro Ltd.
|
|
|
|
*/
|
|
|
|
|
2016-01-11 05:59:17 +00:00
|
|
|
#include <linux/clk.h>
|
2015-12-16 10:59:19 +00:00
|
|
|
#include <linux/delay.h>
|
2019-01-14 14:57:31 +00:00
|
|
|
#include <linux/gpio/consumer.h>
|
2016-01-11 05:59:17 +00:00
|
|
|
#include <linux/interrupt.h>
|
2015-12-16 10:59:19 +00:00
|
|
|
#include <linux/of_irq.h>
|
2016-01-11 05:59:17 +00:00
|
|
|
#include <linux/module.h>
|
2015-12-16 10:59:19 +00:00
|
|
|
#include <linux/pinctrl/consumer.h>
|
2016-01-11 05:59:17 +00:00
|
|
|
#include <linux/platform_device.h>
|
|
|
|
#include <linux/pm.h>
|
|
|
|
#include <linux/regulator/consumer.h>
|
|
|
|
#include <linux/spinlock.h>
|
2015-12-30 21:38:33 +00:00
|
|
|
#include "arche_platform.h"
|
2015-12-16 10:59:19 +00:00
|
|
|
|
2017-05-16 08:01:38 +00:00
|
|
|
static void apb_bootret_deassert(struct device *dev);
|
|
|
|
|
2015-12-16 10:59:19 +00:00
|
|
|
struct arche_apb_ctrl_drvdata {
|
|
|
|
/* Control GPIO signals to and from AP <=> AP Bridges */
|
2019-01-14 14:57:31 +00:00
|
|
|
struct gpio_desc *resetn;
|
|
|
|
struct gpio_desc *boot_ret;
|
|
|
|
struct gpio_desc *pwroff;
|
|
|
|
struct gpio_desc *wake_in;
|
|
|
|
struct gpio_desc *wake_out;
|
|
|
|
struct gpio_desc *pwrdn;
|
2015-12-16 10:59:19 +00:00
|
|
|
|
2016-02-12 20:34:02 +00:00
|
|
|
enum arche_platform_state state;
|
greybus: arche-apb-ctrl: Introduce ara,init-disable property for APB
New DT property "ara,init-disable" will allow user to disable
APB1 or APB2 during boot and enable it only when needed through
command prompt via sysfs interface.
- To disable APB2 during boot, specify "ara,init-disable" property in
respective APB node.
- How to check the state
# cat /sys/devices/arche_platform.*/apb*/state
It should be 'off', if 'ara,init-disable' enabled in DT.
- During runtime if user/developer desired to enable APB2 (strictly and
only for development purpose) then respective APB can be enabled
through,
# echo active > /sys/devices/arche_platform.*/apb*/state
Note:
- If APB device is in 'off,disabled' state, then no state transitions
are permitted.
- User/developer must first activate APB device
# echo active > /sys/devices/arche_platform.*/apb*/state
This will clear the 'init-disable' flag and allow state transition
from here onwards.
Note that, 'off,disabled' is only indicative state and is only
applicable during init/boot.
Testing Done: Tested on EVT1.2 and DB3.5 platform
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-02-12 20:34:14 +00:00
|
|
|
bool init_disabled;
|
2015-12-16 10:59:19 +00:00
|
|
|
|
|
|
|
struct regulator *vcore;
|
|
|
|
struct regulator *vio;
|
|
|
|
|
2019-01-14 14:57:31 +00:00
|
|
|
struct gpio_desc *clk_en;
|
2015-12-16 10:59:19 +00:00
|
|
|
struct clk *clk;
|
|
|
|
|
|
|
|
struct pinctrl *pinctrl;
|
|
|
|
struct pinctrl_state *pin_default;
|
greybus: arche-platform: Add support for SPI bus sharing for Mihi
In case of Mihi, SPI bus is shared between APB1 and APB2
SPI ROMs, so their FW flashing must be sequential and
arche-platform driver should make sure that they are mutual
exclusive in nature.
So this patch adds certain restrictions to the user of the
arche-platform driver,
- User can no longer flash APB1 and APB2 SPI ROM in parallel
- SPI bus becomes an resource, so user must claim it by moving
respective APB device into FW_FLASHING mode and release it
by exiting FW_FLASHING mode. User can exit FW_FLASHING mode by
switching to any other modes (ACTIVE, OFF, STANDBY).
- If APB1 is in FW_FLASHING mode, APB2 can no longer enter into
FW_FLASHING mode. User will get -EBUSY.
Having said that, while APB1 is into FW_FLASHING mode,
APB2 can independently boot from its own SPI ROM.
Testing Done: Tested by simulating usecase on EVT2.
- Made sure that APB1 and APB2 FW_FLASHING mode is mutual exclusive
in nature. Confirmed that an attempt on second device return -EBUSY.
- Added simulating code, where printed state of dummy gpio for
spi-en and verified that it shows right pin status for both APBs
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-07-28 08:17:37 +00:00
|
|
|
|
|
|
|
/* V2: SPI Bus control */
|
2019-01-14 14:57:31 +00:00
|
|
|
struct gpio_desc *spi_en;
|
greybus: arche-platform: Add support for SPI bus sharing for Mihi
In case of Mihi, SPI bus is shared between APB1 and APB2
SPI ROMs, so their FW flashing must be sequential and
arche-platform driver should make sure that they are mutual
exclusive in nature.
So this patch adds certain restrictions to the user of the
arche-platform driver,
- User can no longer flash APB1 and APB2 SPI ROM in parallel
- SPI bus becomes an resource, so user must claim it by moving
respective APB device into FW_FLASHING mode and release it
by exiting FW_FLASHING mode. User can exit FW_FLASHING mode by
switching to any other modes (ACTIVE, OFF, STANDBY).
- If APB1 is in FW_FLASHING mode, APB2 can no longer enter into
FW_FLASHING mode. User will get -EBUSY.
Having said that, while APB1 is into FW_FLASHING mode,
APB2 can independently boot from its own SPI ROM.
Testing Done: Tested by simulating usecase on EVT2.
- Made sure that APB1 and APB2 FW_FLASHING mode is mutual exclusive
in nature. Confirmed that an attempt on second device return -EBUSY.
- Added simulating code, where printed state of dummy gpio for
spi-en and verified that it shows right pin status for both APBs
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-07-28 08:17:37 +00:00
|
|
|
bool spi_en_polarity_high;
|
2015-12-16 10:59:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Note that these low level api's are active high
|
|
|
|
*/
|
2019-01-14 14:57:31 +00:00
|
|
|
static inline void deassert_reset(struct gpio_desc *gpio)
|
2015-12-16 10:59:19 +00:00
|
|
|
{
|
2019-01-14 14:57:31 +00:00
|
|
|
gpiod_set_raw_value(gpio, 1);
|
2015-12-16 10:59:19 +00:00
|
|
|
}
|
|
|
|
|
2019-01-14 14:57:31 +00:00
|
|
|
static inline void assert_reset(struct gpio_desc *gpio)
|
2015-12-16 10:59:19 +00:00
|
|
|
{
|
2019-01-14 14:57:31 +00:00
|
|
|
gpiod_set_raw_value(gpio, 0);
|
2015-12-16 10:59:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Note: Please do not modify the below sequence, as it is as per the spec
|
|
|
|
*/
|
2016-02-12 20:34:15 +00:00
|
|
|
static int coldboot_seq(struct platform_device *pdev)
|
2015-12-16 10:59:19 +00:00
|
|
|
{
|
|
|
|
struct device *dev = &pdev->dev;
|
2016-02-12 20:34:12 +00:00
|
|
|
struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
|
2015-12-16 10:59:19 +00:00
|
|
|
int ret;
|
|
|
|
|
2016-02-22 11:57:26 +00:00
|
|
|
if (apb->init_disabled ||
|
2017-12-17 17:56:26 +00:00
|
|
|
apb->state == ARCHE_PLATFORM_STATE_ACTIVE)
|
greybus: arche-apb-ctrl: Introduce ara,init-disable property for APB
New DT property "ara,init-disable" will allow user to disable
APB1 or APB2 during boot and enable it only when needed through
command prompt via sysfs interface.
- To disable APB2 during boot, specify "ara,init-disable" property in
respective APB node.
- How to check the state
# cat /sys/devices/arche_platform.*/apb*/state
It should be 'off', if 'ara,init-disable' enabled in DT.
- During runtime if user/developer desired to enable APB2 (strictly and
only for development purpose) then respective APB can be enabled
through,
# echo active > /sys/devices/arche_platform.*/apb*/state
Note:
- If APB device is in 'off,disabled' state, then no state transitions
are permitted.
- User/developer must first activate APB device
# echo active > /sys/devices/arche_platform.*/apb*/state
This will clear the 'init-disable' flag and allow state transition
from here onwards.
Note that, 'off,disabled' is only indicative state and is only
applicable during init/boot.
Testing Done: Tested on EVT1.2 and DB3.5 platform
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-02-12 20:34:14 +00:00
|
|
|
return 0;
|
|
|
|
|
2015-12-16 10:59:19 +00:00
|
|
|
/* Hold APB in reset state */
|
2019-01-14 14:57:31 +00:00
|
|
|
assert_reset(apb->resetn);
|
2015-12-16 10:59:19 +00:00
|
|
|
|
2019-01-14 14:57:31 +00:00
|
|
|
if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && apb->spi_en)
|
|
|
|
devm_gpiod_put(dev, apb->spi_en);
|
greybus: arche-platform: Add support for SPI bus sharing for Mihi
In case of Mihi, SPI bus is shared between APB1 and APB2
SPI ROMs, so their FW flashing must be sequential and
arche-platform driver should make sure that they are mutual
exclusive in nature.
So this patch adds certain restrictions to the user of the
arche-platform driver,
- User can no longer flash APB1 and APB2 SPI ROM in parallel
- SPI bus becomes an resource, so user must claim it by moving
respective APB device into FW_FLASHING mode and release it
by exiting FW_FLASHING mode. User can exit FW_FLASHING mode by
switching to any other modes (ACTIVE, OFF, STANDBY).
- If APB1 is in FW_FLASHING mode, APB2 can no longer enter into
FW_FLASHING mode. User will get -EBUSY.
Having said that, while APB1 is into FW_FLASHING mode,
APB2 can independently boot from its own SPI ROM.
Testing Done: Tested by simulating usecase on EVT2.
- Made sure that APB1 and APB2 FW_FLASHING mode is mutual exclusive
in nature. Confirmed that an attempt on second device return -EBUSY.
- Added simulating code, where printed state of dummy gpio for
spi-en and verified that it shows right pin status for both APBs
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-07-28 08:17:37 +00:00
|
|
|
|
2015-12-16 10:59:19 +00:00
|
|
|
/* Enable power to APB */
|
2016-01-11 05:59:12 +00:00
|
|
|
if (!IS_ERR(apb->vcore)) {
|
2015-12-16 10:59:19 +00:00
|
|
|
ret = regulator_enable(apb->vcore);
|
|
|
|
if (ret) {
|
|
|
|
dev_err(dev, "failed to enable core regulator\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
2016-01-13 20:36:47 +00:00
|
|
|
|
2016-01-11 05:59:12 +00:00
|
|
|
if (!IS_ERR(apb->vio)) {
|
2015-12-16 10:59:19 +00:00
|
|
|
ret = regulator_enable(apb->vio);
|
|
|
|
if (ret) {
|
|
|
|
dev_err(dev, "failed to enable IO regulator\n");
|
2016-02-12 20:34:09 +00:00
|
|
|
return ret;
|
2015-12-16 10:59:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-05 13:03:26 +00:00
|
|
|
apb_bootret_deassert(dev);
|
2016-01-13 20:36:47 +00:00
|
|
|
|
|
|
|
/* On DB3 clock was not mandatory */
|
2019-01-14 14:57:31 +00:00
|
|
|
if (apb->clk_en)
|
|
|
|
gpiod_set_value(apb->clk_en, 1);
|
2016-01-13 20:36:47 +00:00
|
|
|
|
|
|
|
usleep_range(100, 200);
|
2015-12-16 10:59:19 +00:00
|
|
|
|
2016-02-12 20:34:09 +00:00
|
|
|
/* deassert reset to APB : Active-low signal */
|
2019-01-14 14:57:31 +00:00
|
|
|
deassert_reset(apb->resetn);
|
2016-01-11 05:59:15 +00:00
|
|
|
|
2016-02-12 20:34:09 +00:00
|
|
|
apb->state = ARCHE_PLATFORM_STATE_ACTIVE;
|
2015-12-16 10:59:19 +00:00
|
|
|
|
2016-02-12 20:34:09 +00:00
|
|
|
return 0;
|
2015-12-16 10:59:19 +00:00
|
|
|
}
|
|
|
|
|
2016-02-12 20:34:15 +00:00
|
|
|
static int fw_flashing_seq(struct platform_device *pdev)
|
2016-02-12 20:34:13 +00:00
|
|
|
{
|
|
|
|
struct device *dev = &pdev->dev;
|
|
|
|
struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
|
|
|
|
int ret;
|
|
|
|
|
2016-02-22 11:57:26 +00:00
|
|
|
if (apb->init_disabled ||
|
2017-12-17 17:56:26 +00:00
|
|
|
apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING)
|
greybus: arche-apb-ctrl: Introduce ara,init-disable property for APB
New DT property "ara,init-disable" will allow user to disable
APB1 or APB2 during boot and enable it only when needed through
command prompt via sysfs interface.
- To disable APB2 during boot, specify "ara,init-disable" property in
respective APB node.
- How to check the state
# cat /sys/devices/arche_platform.*/apb*/state
It should be 'off', if 'ara,init-disable' enabled in DT.
- During runtime if user/developer desired to enable APB2 (strictly and
only for development purpose) then respective APB can be enabled
through,
# echo active > /sys/devices/arche_platform.*/apb*/state
Note:
- If APB device is in 'off,disabled' state, then no state transitions
are permitted.
- User/developer must first activate APB device
# echo active > /sys/devices/arche_platform.*/apb*/state
This will clear the 'init-disable' flag and allow state transition
from here onwards.
Note that, 'off,disabled' is only indicative state and is only
applicable during init/boot.
Testing Done: Tested on EVT1.2 and DB3.5 platform
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-02-12 20:34:14 +00:00
|
|
|
return 0;
|
|
|
|
|
2016-02-12 20:34:13 +00:00
|
|
|
ret = regulator_enable(apb->vcore);
|
|
|
|
if (ret) {
|
|
|
|
dev_err(dev, "failed to enable core regulator\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = regulator_enable(apb->vio);
|
|
|
|
if (ret) {
|
|
|
|
dev_err(dev, "failed to enable IO regulator\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-01-14 14:57:31 +00:00
|
|
|
if (apb->spi_en) {
|
greybus: arche-platform: Add support for SPI bus sharing for Mihi
In case of Mihi, SPI bus is shared between APB1 and APB2
SPI ROMs, so their FW flashing must be sequential and
arche-platform driver should make sure that they are mutual
exclusive in nature.
So this patch adds certain restrictions to the user of the
arche-platform driver,
- User can no longer flash APB1 and APB2 SPI ROM in parallel
- SPI bus becomes an resource, so user must claim it by moving
respective APB device into FW_FLASHING mode and release it
by exiting FW_FLASHING mode. User can exit FW_FLASHING mode by
switching to any other modes (ACTIVE, OFF, STANDBY).
- If APB1 is in FW_FLASHING mode, APB2 can no longer enter into
FW_FLASHING mode. User will get -EBUSY.
Having said that, while APB1 is into FW_FLASHING mode,
APB2 can independently boot from its own SPI ROM.
Testing Done: Tested by simulating usecase on EVT2.
- Made sure that APB1 and APB2 FW_FLASHING mode is mutual exclusive
in nature. Confirmed that an attempt on second device return -EBUSY.
- Added simulating code, where printed state of dummy gpio for
spi-en and verified that it shows right pin status for both APBs
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-07-28 08:17:37 +00:00
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
if (apb->spi_en_polarity_high)
|
2019-01-14 14:57:31 +00:00
|
|
|
flags = GPIOD_OUT_HIGH;
|
greybus: arche-platform: Add support for SPI bus sharing for Mihi
In case of Mihi, SPI bus is shared between APB1 and APB2
SPI ROMs, so their FW flashing must be sequential and
arche-platform driver should make sure that they are mutual
exclusive in nature.
So this patch adds certain restrictions to the user of the
arche-platform driver,
- User can no longer flash APB1 and APB2 SPI ROM in parallel
- SPI bus becomes an resource, so user must claim it by moving
respective APB device into FW_FLASHING mode and release it
by exiting FW_FLASHING mode. User can exit FW_FLASHING mode by
switching to any other modes (ACTIVE, OFF, STANDBY).
- If APB1 is in FW_FLASHING mode, APB2 can no longer enter into
FW_FLASHING mode. User will get -EBUSY.
Having said that, while APB1 is into FW_FLASHING mode,
APB2 can independently boot from its own SPI ROM.
Testing Done: Tested by simulating usecase on EVT2.
- Made sure that APB1 and APB2 FW_FLASHING mode is mutual exclusive
in nature. Confirmed that an attempt on second device return -EBUSY.
- Added simulating code, where printed state of dummy gpio for
spi-en and verified that it shows right pin status for both APBs
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-07-28 08:17:37 +00:00
|
|
|
else
|
2019-01-14 14:57:31 +00:00
|
|
|
flags = GPIOD_OUT_LOW;
|
greybus: arche-platform: Add support for SPI bus sharing for Mihi
In case of Mihi, SPI bus is shared between APB1 and APB2
SPI ROMs, so their FW flashing must be sequential and
arche-platform driver should make sure that they are mutual
exclusive in nature.
So this patch adds certain restrictions to the user of the
arche-platform driver,
- User can no longer flash APB1 and APB2 SPI ROM in parallel
- SPI bus becomes an resource, so user must claim it by moving
respective APB device into FW_FLASHING mode and release it
by exiting FW_FLASHING mode. User can exit FW_FLASHING mode by
switching to any other modes (ACTIVE, OFF, STANDBY).
- If APB1 is in FW_FLASHING mode, APB2 can no longer enter into
FW_FLASHING mode. User will get -EBUSY.
Having said that, while APB1 is into FW_FLASHING mode,
APB2 can independently boot from its own SPI ROM.
Testing Done: Tested by simulating usecase on EVT2.
- Made sure that APB1 and APB2 FW_FLASHING mode is mutual exclusive
in nature. Confirmed that an attempt on second device return -EBUSY.
- Added simulating code, where printed state of dummy gpio for
spi-en and verified that it shows right pin status for both APBs
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-07-28 08:17:37 +00:00
|
|
|
|
2019-01-14 14:57:31 +00:00
|
|
|
apb->spi_en = devm_gpiod_get(dev, "spi-en", flags);
|
|
|
|
if (IS_ERR(apb->spi_en)) {
|
|
|
|
ret = PTR_ERR(apb->spi_en);
|
|
|
|
dev_err(dev, "Failed requesting SPI bus en GPIO: %d\n",
|
|
|
|
ret);
|
greybus: arche-platform: Add support for SPI bus sharing for Mihi
In case of Mihi, SPI bus is shared between APB1 and APB2
SPI ROMs, so their FW flashing must be sequential and
arche-platform driver should make sure that they are mutual
exclusive in nature.
So this patch adds certain restrictions to the user of the
arche-platform driver,
- User can no longer flash APB1 and APB2 SPI ROM in parallel
- SPI bus becomes an resource, so user must claim it by moving
respective APB device into FW_FLASHING mode and release it
by exiting FW_FLASHING mode. User can exit FW_FLASHING mode by
switching to any other modes (ACTIVE, OFF, STANDBY).
- If APB1 is in FW_FLASHING mode, APB2 can no longer enter into
FW_FLASHING mode. User will get -EBUSY.
Having said that, while APB1 is into FW_FLASHING mode,
APB2 can independently boot from its own SPI ROM.
Testing Done: Tested by simulating usecase on EVT2.
- Made sure that APB1 and APB2 FW_FLASHING mode is mutual exclusive
in nature. Confirmed that an attempt on second device return -EBUSY.
- Added simulating code, where printed state of dummy gpio for
spi-en and verified that it shows right pin status for both APBs
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-07-28 08:17:37 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-12 20:34:13 +00:00
|
|
|
/* for flashing device should be in reset state */
|
2019-01-14 14:57:31 +00:00
|
|
|
assert_reset(apb->resetn);
|
2016-02-12 20:34:13 +00:00
|
|
|
apb->state = ARCHE_PLATFORM_STATE_FW_FLASHING;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-02-12 20:34:15 +00:00
|
|
|
static int standby_boot_seq(struct platform_device *pdev)
|
2016-02-12 20:34:13 +00:00
|
|
|
{
|
greybus: arche-platform: Add support for SPI bus sharing for Mihi
In case of Mihi, SPI bus is shared between APB1 and APB2
SPI ROMs, so their FW flashing must be sequential and
arche-platform driver should make sure that they are mutual
exclusive in nature.
So this patch adds certain restrictions to the user of the
arche-platform driver,
- User can no longer flash APB1 and APB2 SPI ROM in parallel
- SPI bus becomes an resource, so user must claim it by moving
respective APB device into FW_FLASHING mode and release it
by exiting FW_FLASHING mode. User can exit FW_FLASHING mode by
switching to any other modes (ACTIVE, OFF, STANDBY).
- If APB1 is in FW_FLASHING mode, APB2 can no longer enter into
FW_FLASHING mode. User will get -EBUSY.
Having said that, while APB1 is into FW_FLASHING mode,
APB2 can independently boot from its own SPI ROM.
Testing Done: Tested by simulating usecase on EVT2.
- Made sure that APB1 and APB2 FW_FLASHING mode is mutual exclusive
in nature. Confirmed that an attempt on second device return -EBUSY.
- Added simulating code, where printed state of dummy gpio for
spi-en and verified that it shows right pin status for both APBs
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-07-28 08:17:37 +00:00
|
|
|
struct device *dev = &pdev->dev;
|
2016-02-12 20:34:13 +00:00
|
|
|
struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
|
|
|
|
|
greybus: arche-apb-ctrl: Introduce ara,init-disable property for APB
New DT property "ara,init-disable" will allow user to disable
APB1 or APB2 during boot and enable it only when needed through
command prompt via sysfs interface.
- To disable APB2 during boot, specify "ara,init-disable" property in
respective APB node.
- How to check the state
# cat /sys/devices/arche_platform.*/apb*/state
It should be 'off', if 'ara,init-disable' enabled in DT.
- During runtime if user/developer desired to enable APB2 (strictly and
only for development purpose) then respective APB can be enabled
through,
# echo active > /sys/devices/arche_platform.*/apb*/state
Note:
- If APB device is in 'off,disabled' state, then no state transitions
are permitted.
- User/developer must first activate APB device
# echo active > /sys/devices/arche_platform.*/apb*/state
This will clear the 'init-disable' flag and allow state transition
from here onwards.
Note that, 'off,disabled' is only indicative state and is only
applicable during init/boot.
Testing Done: Tested on EVT1.2 and DB3.5 platform
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-02-12 20:34:14 +00:00
|
|
|
if (apb->init_disabled)
|
|
|
|
return 0;
|
|
|
|
|
2017-02-09 16:30:11 +00:00
|
|
|
/*
|
|
|
|
* Even if it is in OFF state,
|
|
|
|
* then we do not want to change the state
|
|
|
|
*/
|
2016-02-22 11:57:26 +00:00
|
|
|
if (apb->state == ARCHE_PLATFORM_STATE_STANDBY ||
|
2017-12-17 17:56:26 +00:00
|
|
|
apb->state == ARCHE_PLATFORM_STATE_OFF)
|
2016-02-12 20:34:13 +00:00
|
|
|
return 0;
|
|
|
|
|
2019-01-14 14:57:31 +00:00
|
|
|
if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && apb->spi_en)
|
|
|
|
devm_gpiod_put(dev, apb->spi_en);
|
greybus: arche-platform: Add support for SPI bus sharing for Mihi
In case of Mihi, SPI bus is shared between APB1 and APB2
SPI ROMs, so their FW flashing must be sequential and
arche-platform driver should make sure that they are mutual
exclusive in nature.
So this patch adds certain restrictions to the user of the
arche-platform driver,
- User can no longer flash APB1 and APB2 SPI ROM in parallel
- SPI bus becomes an resource, so user must claim it by moving
respective APB device into FW_FLASHING mode and release it
by exiting FW_FLASHING mode. User can exit FW_FLASHING mode by
switching to any other modes (ACTIVE, OFF, STANDBY).
- If APB1 is in FW_FLASHING mode, APB2 can no longer enter into
FW_FLASHING mode. User will get -EBUSY.
Having said that, while APB1 is into FW_FLASHING mode,
APB2 can independently boot from its own SPI ROM.
Testing Done: Tested by simulating usecase on EVT2.
- Made sure that APB1 and APB2 FW_FLASHING mode is mutual exclusive
in nature. Confirmed that an attempt on second device return -EBUSY.
- Added simulating code, where printed state of dummy gpio for
spi-en and verified that it shows right pin status for both APBs
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-07-28 08:17:37 +00:00
|
|
|
|
2016-02-12 20:34:13 +00:00
|
|
|
/*
|
|
|
|
* As per WDM spec, do nothing
|
|
|
|
*
|
|
|
|
* Pasted from WDM spec,
|
|
|
|
* - A falling edge on POWEROFF_L is detected (a)
|
|
|
|
* - WDM enters standby mode, but no output signals are changed
|
2016-10-03 14:45:15 +00:00
|
|
|
*/
|
2016-02-12 20:34:13 +00:00
|
|
|
|
|
|
|
/* TODO: POWEROFF_L is input to WDM module */
|
|
|
|
apb->state = ARCHE_PLATFORM_STATE_STANDBY;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-02-12 20:34:15 +00:00
|
|
|
static void poweroff_seq(struct platform_device *pdev)
|
2016-02-12 20:34:10 +00:00
|
|
|
{
|
greybus: arche-platform: Add support for SPI bus sharing for Mihi
In case of Mihi, SPI bus is shared between APB1 and APB2
SPI ROMs, so their FW flashing must be sequential and
arche-platform driver should make sure that they are mutual
exclusive in nature.
So this patch adds certain restrictions to the user of the
arche-platform driver,
- User can no longer flash APB1 and APB2 SPI ROM in parallel
- SPI bus becomes an resource, so user must claim it by moving
respective APB device into FW_FLASHING mode and release it
by exiting FW_FLASHING mode. User can exit FW_FLASHING mode by
switching to any other modes (ACTIVE, OFF, STANDBY).
- If APB1 is in FW_FLASHING mode, APB2 can no longer enter into
FW_FLASHING mode. User will get -EBUSY.
Having said that, while APB1 is into FW_FLASHING mode,
APB2 can independently boot from its own SPI ROM.
Testing Done: Tested by simulating usecase on EVT2.
- Made sure that APB1 and APB2 FW_FLASHING mode is mutual exclusive
in nature. Confirmed that an attempt on second device return -EBUSY.
- Added simulating code, where printed state of dummy gpio for
spi-en and verified that it shows right pin status for both APBs
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-07-28 08:17:37 +00:00
|
|
|
struct device *dev = &pdev->dev;
|
2016-02-12 20:34:12 +00:00
|
|
|
struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
|
|
|
|
|
2016-02-22 11:57:26 +00:00
|
|
|
if (apb->init_disabled || apb->state == ARCHE_PLATFORM_STATE_OFF)
|
greybus: arche-apb-ctrl: Introduce ara,init-disable property for APB
New DT property "ara,init-disable" will allow user to disable
APB1 or APB2 during boot and enable it only when needed through
command prompt via sysfs interface.
- To disable APB2 during boot, specify "ara,init-disable" property in
respective APB node.
- How to check the state
# cat /sys/devices/arche_platform.*/apb*/state
It should be 'off', if 'ara,init-disable' enabled in DT.
- During runtime if user/developer desired to enable APB2 (strictly and
only for development purpose) then respective APB can be enabled
through,
# echo active > /sys/devices/arche_platform.*/apb*/state
Note:
- If APB device is in 'off,disabled' state, then no state transitions
are permitted.
- User/developer must first activate APB device
# echo active > /sys/devices/arche_platform.*/apb*/state
This will clear the 'init-disable' flag and allow state transition
from here onwards.
Note that, 'off,disabled' is only indicative state and is only
applicable during init/boot.
Testing Done: Tested on EVT1.2 and DB3.5 platform
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-02-12 20:34:14 +00:00
|
|
|
return;
|
|
|
|
|
2019-01-14 14:57:31 +00:00
|
|
|
if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING && apb->spi_en)
|
|
|
|
devm_gpiod_put(dev, apb->spi_en);
|
greybus: arche-platform: Add support for SPI bus sharing for Mihi
In case of Mihi, SPI bus is shared between APB1 and APB2
SPI ROMs, so their FW flashing must be sequential and
arche-platform driver should make sure that they are mutual
exclusive in nature.
So this patch adds certain restrictions to the user of the
arche-platform driver,
- User can no longer flash APB1 and APB2 SPI ROM in parallel
- SPI bus becomes an resource, so user must claim it by moving
respective APB device into FW_FLASHING mode and release it
by exiting FW_FLASHING mode. User can exit FW_FLASHING mode by
switching to any other modes (ACTIVE, OFF, STANDBY).
- If APB1 is in FW_FLASHING mode, APB2 can no longer enter into
FW_FLASHING mode. User will get -EBUSY.
Having said that, while APB1 is into FW_FLASHING mode,
APB2 can independently boot from its own SPI ROM.
Testing Done: Tested by simulating usecase on EVT2.
- Made sure that APB1 and APB2 FW_FLASHING mode is mutual exclusive
in nature. Confirmed that an attempt on second device return -EBUSY.
- Added simulating code, where printed state of dummy gpio for
spi-en and verified that it shows right pin status for both APBs
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-07-28 08:17:37 +00:00
|
|
|
|
2016-02-12 20:34:10 +00:00
|
|
|
/* disable the clock */
|
2019-01-14 14:57:31 +00:00
|
|
|
if (apb->clk_en)
|
|
|
|
gpiod_set_value(apb->clk_en, 0);
|
2016-02-12 20:34:10 +00:00
|
|
|
|
|
|
|
if (!IS_ERR(apb->vcore) && regulator_is_enabled(apb->vcore) > 0)
|
|
|
|
regulator_disable(apb->vcore);
|
|
|
|
|
|
|
|
if (!IS_ERR(apb->vio) && regulator_is_enabled(apb->vio) > 0)
|
|
|
|
regulator_disable(apb->vio);
|
|
|
|
|
|
|
|
/* As part of exit, put APB back in reset state */
|
2019-01-14 14:57:31 +00:00
|
|
|
assert_reset(apb->resetn);
|
2016-02-12 20:34:10 +00:00
|
|
|
apb->state = ARCHE_PLATFORM_STATE_OFF;
|
|
|
|
|
|
|
|
/* TODO: May have to send an event to SVC about this exit */
|
|
|
|
}
|
|
|
|
|
2017-05-16 08:01:38 +00:00
|
|
|
static void apb_bootret_deassert(struct device *dev)
|
2016-06-05 13:03:26 +00:00
|
|
|
{
|
|
|
|
struct arche_apb_ctrl_drvdata *apb = dev_get_drvdata(dev);
|
|
|
|
|
2019-01-14 14:57:31 +00:00
|
|
|
gpiod_set_value(apb->boot_ret, 0);
|
2016-06-05 13:03:26 +00:00
|
|
|
}
|
|
|
|
|
2016-02-12 20:34:16 +00:00
|
|
|
int apb_ctrl_coldboot(struct device *dev)
|
|
|
|
{
|
|
|
|
return coldboot_seq(to_platform_device(dev));
|
|
|
|
}
|
|
|
|
|
|
|
|
int apb_ctrl_fw_flashing(struct device *dev)
|
|
|
|
{
|
|
|
|
return fw_flashing_seq(to_platform_device(dev));
|
|
|
|
}
|
|
|
|
|
|
|
|
int apb_ctrl_standby_boot(struct device *dev)
|
|
|
|
{
|
|
|
|
return standby_boot_seq(to_platform_device(dev));
|
|
|
|
}
|
|
|
|
|
|
|
|
void apb_ctrl_poweroff(struct device *dev)
|
|
|
|
{
|
|
|
|
poweroff_seq(to_platform_device(dev));
|
|
|
|
}
|
|
|
|
|
2016-02-12 20:34:13 +00:00
|
|
|
static ssize_t state_store(struct device *dev,
|
2017-12-17 17:56:26 +00:00
|
|
|
struct device_attribute *attr,
|
|
|
|
const char *buf, size_t count)
|
2016-02-12 20:34:13 +00:00
|
|
|
{
|
|
|
|
struct platform_device *pdev = to_platform_device(dev);
|
|
|
|
struct arche_apb_ctrl_drvdata *apb = platform_get_drvdata(pdev);
|
|
|
|
int ret = 0;
|
greybus: arche-apb-ctrl: Introduce ara,init-disable property for APB
New DT property "ara,init-disable" will allow user to disable
APB1 or APB2 during boot and enable it only when needed through
command prompt via sysfs interface.
- To disable APB2 during boot, specify "ara,init-disable" property in
respective APB node.
- How to check the state
# cat /sys/devices/arche_platform.*/apb*/state
It should be 'off', if 'ara,init-disable' enabled in DT.
- During runtime if user/developer desired to enable APB2 (strictly and
only for development purpose) then respective APB can be enabled
through,
# echo active > /sys/devices/arche_platform.*/apb*/state
Note:
- If APB device is in 'off,disabled' state, then no state transitions
are permitted.
- User/developer must first activate APB device
# echo active > /sys/devices/arche_platform.*/apb*/state
This will clear the 'init-disable' flag and allow state transition
from here onwards.
Note that, 'off,disabled' is only indicative state and is only
applicable during init/boot.
Testing Done: Tested on EVT1.2 and DB3.5 platform
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-02-12 20:34:14 +00:00
|
|
|
bool is_disabled;
|
2016-02-12 20:34:13 +00:00
|
|
|
|
|
|
|
if (sysfs_streq(buf, "off")) {
|
|
|
|
if (apb->state == ARCHE_PLATFORM_STATE_OFF)
|
|
|
|
return count;
|
|
|
|
|
2016-02-12 20:34:15 +00:00
|
|
|
poweroff_seq(pdev);
|
2016-02-12 20:34:13 +00:00
|
|
|
} else if (sysfs_streq(buf, "active")) {
|
|
|
|
if (apb->state == ARCHE_PLATFORM_STATE_ACTIVE)
|
|
|
|
return count;
|
|
|
|
|
2016-02-12 20:34:15 +00:00
|
|
|
poweroff_seq(pdev);
|
greybus: arche-apb-ctrl: Introduce ara,init-disable property for APB
New DT property "ara,init-disable" will allow user to disable
APB1 or APB2 during boot and enable it only when needed through
command prompt via sysfs interface.
- To disable APB2 during boot, specify "ara,init-disable" property in
respective APB node.
- How to check the state
# cat /sys/devices/arche_platform.*/apb*/state
It should be 'off', if 'ara,init-disable' enabled in DT.
- During runtime if user/developer desired to enable APB2 (strictly and
only for development purpose) then respective APB can be enabled
through,
# echo active > /sys/devices/arche_platform.*/apb*/state
Note:
- If APB device is in 'off,disabled' state, then no state transitions
are permitted.
- User/developer must first activate APB device
# echo active > /sys/devices/arche_platform.*/apb*/state
This will clear the 'init-disable' flag and allow state transition
from here onwards.
Note that, 'off,disabled' is only indicative state and is only
applicable during init/boot.
Testing Done: Tested on EVT1.2 and DB3.5 platform
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-02-12 20:34:14 +00:00
|
|
|
is_disabled = apb->init_disabled;
|
|
|
|
apb->init_disabled = false;
|
2016-02-12 20:34:15 +00:00
|
|
|
ret = coldboot_seq(pdev);
|
greybus: arche-apb-ctrl: Introduce ara,init-disable property for APB
New DT property "ara,init-disable" will allow user to disable
APB1 or APB2 during boot and enable it only when needed through
command prompt via sysfs interface.
- To disable APB2 during boot, specify "ara,init-disable" property in
respective APB node.
- How to check the state
# cat /sys/devices/arche_platform.*/apb*/state
It should be 'off', if 'ara,init-disable' enabled in DT.
- During runtime if user/developer desired to enable APB2 (strictly and
only for development purpose) then respective APB can be enabled
through,
# echo active > /sys/devices/arche_platform.*/apb*/state
Note:
- If APB device is in 'off,disabled' state, then no state transitions
are permitted.
- User/developer must first activate APB device
# echo active > /sys/devices/arche_platform.*/apb*/state
This will clear the 'init-disable' flag and allow state transition
from here onwards.
Note that, 'off,disabled' is only indicative state and is only
applicable during init/boot.
Testing Done: Tested on EVT1.2 and DB3.5 platform
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-02-12 20:34:14 +00:00
|
|
|
if (ret)
|
|
|
|
apb->init_disabled = is_disabled;
|
2016-02-12 20:34:13 +00:00
|
|
|
} else if (sysfs_streq(buf, "standby")) {
|
|
|
|
if (apb->state == ARCHE_PLATFORM_STATE_STANDBY)
|
|
|
|
return count;
|
|
|
|
|
2016-02-12 20:34:15 +00:00
|
|
|
ret = standby_boot_seq(pdev);
|
2016-02-12 20:34:13 +00:00
|
|
|
} else if (sysfs_streq(buf, "fw_flashing")) {
|
|
|
|
if (apb->state == ARCHE_PLATFORM_STATE_FW_FLASHING)
|
|
|
|
return count;
|
|
|
|
|
2016-10-03 10:51:09 +00:00
|
|
|
/*
|
|
|
|
* First we want to make sure we power off everything
|
|
|
|
* and then enter FW flashing state
|
|
|
|
*/
|
2016-02-12 20:34:15 +00:00
|
|
|
poweroff_seq(pdev);
|
|
|
|
ret = fw_flashing_seq(pdev);
|
2016-02-12 20:34:13 +00:00
|
|
|
} else {
|
|
|
|
dev_err(dev, "unknown state\n");
|
|
|
|
ret = -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret ? ret : count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ssize_t state_show(struct device *dev,
|
2017-12-17 17:56:26 +00:00
|
|
|
struct device_attribute *attr, char *buf)
|
2016-02-12 20:34:13 +00:00
|
|
|
{
|
|
|
|
struct arche_apb_ctrl_drvdata *apb = dev_get_drvdata(dev);
|
|
|
|
|
|
|
|
switch (apb->state) {
|
|
|
|
case ARCHE_PLATFORM_STATE_OFF:
|
greybus: arche-apb-ctrl: Introduce ara,init-disable property for APB
New DT property "ara,init-disable" will allow user to disable
APB1 or APB2 during boot and enable it only when needed through
command prompt via sysfs interface.
- To disable APB2 during boot, specify "ara,init-disable" property in
respective APB node.
- How to check the state
# cat /sys/devices/arche_platform.*/apb*/state
It should be 'off', if 'ara,init-disable' enabled in DT.
- During runtime if user/developer desired to enable APB2 (strictly and
only for development purpose) then respective APB can be enabled
through,
# echo active > /sys/devices/arche_platform.*/apb*/state
Note:
- If APB device is in 'off,disabled' state, then no state transitions
are permitted.
- User/developer must first activate APB device
# echo active > /sys/devices/arche_platform.*/apb*/state
This will clear the 'init-disable' flag and allow state transition
from here onwards.
Note that, 'off,disabled' is only indicative state and is only
applicable during init/boot.
Testing Done: Tested on EVT1.2 and DB3.5 platform
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-02-12 20:34:14 +00:00
|
|
|
return sprintf(buf, "off%s\n",
|
|
|
|
apb->init_disabled ? ",disabled" : "");
|
2016-02-12 20:34:13 +00:00
|
|
|
case ARCHE_PLATFORM_STATE_ACTIVE:
|
|
|
|
return sprintf(buf, "active\n");
|
|
|
|
case ARCHE_PLATFORM_STATE_STANDBY:
|
|
|
|
return sprintf(buf, "standby\n");
|
|
|
|
case ARCHE_PLATFORM_STATE_FW_FLASHING:
|
|
|
|
return sprintf(buf, "fw_flashing\n");
|
|
|
|
default:
|
|
|
|
return sprintf(buf, "unknown state\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static DEVICE_ATTR_RW(state);
|
|
|
|
|
2015-12-16 10:59:19 +00:00
|
|
|
static int apb_ctrl_get_devtree_data(struct platform_device *pdev,
|
2017-12-17 17:56:26 +00:00
|
|
|
struct arche_apb_ctrl_drvdata *apb)
|
2015-12-16 10:59:19 +00:00
|
|
|
{
|
|
|
|
struct device *dev = &pdev->dev;
|
2016-02-12 20:34:09 +00:00
|
|
|
int ret;
|
2015-12-16 10:59:19 +00:00
|
|
|
|
2019-01-14 14:57:31 +00:00
|
|
|
apb->resetn = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
|
|
|
|
if (IS_ERR(apb->resetn)) {
|
|
|
|
ret = PTR_ERR(apb->resetn);
|
|
|
|
dev_err(dev, "Failed requesting reset GPIO: %d\n", ret);
|
2016-02-12 20:34:09 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2015-12-16 10:59:19 +00:00
|
|
|
|
2019-01-14 14:57:31 +00:00
|
|
|
apb->boot_ret = devm_gpiod_get(dev, "boot-ret", GPIOD_OUT_LOW);
|
|
|
|
if (IS_ERR(apb->boot_ret)) {
|
|
|
|
ret = PTR_ERR(apb->boot_ret);
|
|
|
|
dev_err(dev, "Failed requesting bootret GPIO: %d\n", ret);
|
2016-02-12 20:34:09 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2015-12-16 10:59:19 +00:00
|
|
|
|
|
|
|
/* It's not mandatory to support power management interface */
|
2019-01-14 14:57:31 +00:00
|
|
|
apb->pwroff = devm_gpiod_get_optional(dev, "pwr-off", GPIOD_IN);
|
|
|
|
if (IS_ERR(apb->pwroff)) {
|
|
|
|
ret = PTR_ERR(apb->pwroff);
|
|
|
|
dev_err(dev, "Failed requesting pwroff_n GPIO: %d\n", ret);
|
2016-02-12 20:34:09 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2015-12-16 10:59:19 +00:00
|
|
|
|
|
|
|
/* Do not make clock mandatory as of now (for DB3) */
|
2019-01-14 14:57:31 +00:00
|
|
|
apb->clk_en = devm_gpiod_get_optional(dev, "clock-en", GPIOD_OUT_LOW);
|
|
|
|
if (IS_ERR(apb->clk_en)) {
|
|
|
|
ret = PTR_ERR(apb->clk_en);
|
|
|
|
dev_err(dev, "Failed requesting APB clock en GPIO: %d\n", ret);
|
|
|
|
return ret;
|
2016-02-12 20:34:09 +00:00
|
|
|
}
|
2015-12-16 10:59:19 +00:00
|
|
|
|
2019-01-14 14:57:31 +00:00
|
|
|
apb->pwrdn = devm_gpiod_get(dev, "pwr-down", GPIOD_OUT_LOW);
|
|
|
|
if (IS_ERR(apb->pwrdn)) {
|
|
|
|
ret = PTR_ERR(apb->pwrdn);
|
|
|
|
dev_warn(dev, "Failed requesting power down GPIO: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
2015-12-16 10:59:19 +00:00
|
|
|
|
|
|
|
/* Regulators are optional, as we may have fixed supply coming in */
|
|
|
|
apb->vcore = devm_regulator_get(dev, "vcore");
|
2016-01-11 05:59:12 +00:00
|
|
|
if (IS_ERR(apb->vcore))
|
2016-01-11 05:59:13 +00:00
|
|
|
dev_warn(dev, "no core regulator found\n");
|
2015-12-16 10:59:19 +00:00
|
|
|
|
|
|
|
apb->vio = devm_regulator_get(dev, "vio");
|
2016-01-11 05:59:12 +00:00
|
|
|
if (IS_ERR(apb->vio))
|
2016-01-11 05:59:13 +00:00
|
|
|
dev_warn(dev, "no IO regulator found\n");
|
2015-12-16 10:59:19 +00:00
|
|
|
|
|
|
|
apb->pinctrl = devm_pinctrl_get(&pdev->dev);
|
|
|
|
if (IS_ERR(apb->pinctrl)) {
|
|
|
|
dev_err(&pdev->dev, "could not get pinctrl handle\n");
|
|
|
|
return PTR_ERR(apb->pinctrl);
|
|
|
|
}
|
|
|
|
apb->pin_default = pinctrl_lookup_state(apb->pinctrl, "default");
|
|
|
|
if (IS_ERR(apb->pin_default)) {
|
|
|
|
dev_err(&pdev->dev, "could not get default pin state\n");
|
|
|
|
return PTR_ERR(apb->pin_default);
|
|
|
|
}
|
|
|
|
|
greybus: arche-platform: Add support for SPI bus sharing for Mihi
In case of Mihi, SPI bus is shared between APB1 and APB2
SPI ROMs, so their FW flashing must be sequential and
arche-platform driver should make sure that they are mutual
exclusive in nature.
So this patch adds certain restrictions to the user of the
arche-platform driver,
- User can no longer flash APB1 and APB2 SPI ROM in parallel
- SPI bus becomes an resource, so user must claim it by moving
respective APB device into FW_FLASHING mode and release it
by exiting FW_FLASHING mode. User can exit FW_FLASHING mode by
switching to any other modes (ACTIVE, OFF, STANDBY).
- If APB1 is in FW_FLASHING mode, APB2 can no longer enter into
FW_FLASHING mode. User will get -EBUSY.
Having said that, while APB1 is into FW_FLASHING mode,
APB2 can independently boot from its own SPI ROM.
Testing Done: Tested by simulating usecase on EVT2.
- Made sure that APB1 and APB2 FW_FLASHING mode is mutual exclusive
in nature. Confirmed that an attempt on second device return -EBUSY.
- Added simulating code, where printed state of dummy gpio for
spi-en and verified that it shows right pin status for both APBs
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-07-28 08:17:37 +00:00
|
|
|
/* Only applicable for platform >= V2 */
|
2019-01-14 14:57:31 +00:00
|
|
|
if (of_property_read_bool(pdev->dev.of_node, "gb,spi-en-active-high"))
|
|
|
|
apb->spi_en_polarity_high = true;
|
greybus: arche-platform: Add support for SPI bus sharing for Mihi
In case of Mihi, SPI bus is shared between APB1 and APB2
SPI ROMs, so their FW flashing must be sequential and
arche-platform driver should make sure that they are mutual
exclusive in nature.
So this patch adds certain restrictions to the user of the
arche-platform driver,
- User can no longer flash APB1 and APB2 SPI ROM in parallel
- SPI bus becomes an resource, so user must claim it by moving
respective APB device into FW_FLASHING mode and release it
by exiting FW_FLASHING mode. User can exit FW_FLASHING mode by
switching to any other modes (ACTIVE, OFF, STANDBY).
- If APB1 is in FW_FLASHING mode, APB2 can no longer enter into
FW_FLASHING mode. User will get -EBUSY.
Having said that, while APB1 is into FW_FLASHING mode,
APB2 can independently boot from its own SPI ROM.
Testing Done: Tested by simulating usecase on EVT2.
- Made sure that APB1 and APB2 FW_FLASHING mode is mutual exclusive
in nature. Confirmed that an attempt on second device return -EBUSY.
- Added simulating code, where printed state of dummy gpio for
spi-en and verified that it shows right pin status for both APBs
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-07-28 08:17:37 +00:00
|
|
|
|
2015-12-16 10:59:19 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-04-20 06:18:37 +00:00
|
|
|
static int arche_apb_ctrl_probe(struct platform_device *pdev)
|
2015-12-16 10:59:19 +00:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct arche_apb_ctrl_drvdata *apb;
|
|
|
|
struct device *dev = &pdev->dev;
|
|
|
|
|
|
|
|
apb = devm_kzalloc(&pdev->dev, sizeof(*apb), GFP_KERNEL);
|
|
|
|
if (!apb)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
ret = apb_ctrl_get_devtree_data(pdev, apb);
|
|
|
|
if (ret) {
|
|
|
|
dev_err(dev, "failed to get apb devicetree data %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-02-12 20:34:11 +00:00
|
|
|
/* Initially set APB to OFF state */
|
|
|
|
apb->state = ARCHE_PLATFORM_STATE_OFF;
|
greybus: arche-apb-ctrl: Introduce ara,init-disable property for APB
New DT property "ara,init-disable" will allow user to disable
APB1 or APB2 during boot and enable it only when needed through
command prompt via sysfs interface.
- To disable APB2 during boot, specify "ara,init-disable" property in
respective APB node.
- How to check the state
# cat /sys/devices/arche_platform.*/apb*/state
It should be 'off', if 'ara,init-disable' enabled in DT.
- During runtime if user/developer desired to enable APB2 (strictly and
only for development purpose) then respective APB can be enabled
through,
# echo active > /sys/devices/arche_platform.*/apb*/state
Note:
- If APB device is in 'off,disabled' state, then no state transitions
are permitted.
- User/developer must first activate APB device
# echo active > /sys/devices/arche_platform.*/apb*/state
This will clear the 'init-disable' flag and allow state transition
from here onwards.
Note that, 'off,disabled' is only indicative state and is only
applicable during init/boot.
Testing Done: Tested on EVT1.2 and DB3.5 platform
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-02-12 20:34:14 +00:00
|
|
|
/* Check whether device needs to be enabled on boot */
|
2016-07-28 08:26:44 +00:00
|
|
|
if (of_property_read_bool(pdev->dev.of_node, "arche,init-disable"))
|
greybus: arche-apb-ctrl: Introduce ara,init-disable property for APB
New DT property "ara,init-disable" will allow user to disable
APB1 or APB2 during boot and enable it only when needed through
command prompt via sysfs interface.
- To disable APB2 during boot, specify "ara,init-disable" property in
respective APB node.
- How to check the state
# cat /sys/devices/arche_platform.*/apb*/state
It should be 'off', if 'ara,init-disable' enabled in DT.
- During runtime if user/developer desired to enable APB2 (strictly and
only for development purpose) then respective APB can be enabled
through,
# echo active > /sys/devices/arche_platform.*/apb*/state
Note:
- If APB device is in 'off,disabled' state, then no state transitions
are permitted.
- User/developer must first activate APB device
# echo active > /sys/devices/arche_platform.*/apb*/state
This will clear the 'init-disable' flag and allow state transition
from here onwards.
Note that, 'off,disabled' is only indicative state and is only
applicable during init/boot.
Testing Done: Tested on EVT1.2 and DB3.5 platform
Signed-off-by: Vaibhav Hiremath <vaibhav.hiremath@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2016-02-12 20:34:14 +00:00
|
|
|
apb->init_disabled = true;
|
2016-02-12 20:34:11 +00:00
|
|
|
|
2016-02-12 20:34:12 +00:00
|
|
|
platform_set_drvdata(pdev, apb);
|
|
|
|
|
2016-02-12 20:34:13 +00:00
|
|
|
/* Create sysfs interface to allow user to change state dynamically */
|
|
|
|
ret = device_create_file(dev, &dev_attr_state);
|
|
|
|
if (ret) {
|
|
|
|
dev_err(dev, "failed to create state file in sysfs\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-12-16 10:59:19 +00:00
|
|
|
dev_info(&pdev->dev, "Device registered successfully\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-04-03 15:39:54 +00:00
|
|
|
static void arche_apb_ctrl_remove(struct platform_device *pdev)
|
2015-12-16 10:59:19 +00:00
|
|
|
{
|
2016-02-12 20:34:13 +00:00
|
|
|
device_remove_file(&pdev->dev, &dev_attr_state);
|
2016-02-12 20:34:15 +00:00
|
|
|
poweroff_seq(pdev);
|
2015-12-16 10:59:19 +00:00
|
|
|
platform_set_drvdata(pdev, NULL);
|
|
|
|
}
|
|
|
|
|
2016-12-17 00:33:02 +00:00
|
|
|
static int __maybe_unused arche_apb_ctrl_suspend(struct device *dev)
|
2015-12-16 10:59:19 +00:00
|
|
|
{
|
|
|
|
/*
|
2016-01-11 05:59:08 +00:00
|
|
|
* If timing profile permits, we may shutdown bridge
|
2015-12-16 10:59:19 +00:00
|
|
|
* completely
|
|
|
|
*
|
|
|
|
* TODO: sequence ??
|
|
|
|
*
|
|
|
|
* Also, need to make sure we meet precondition for unipro suspend
|
|
|
|
* Precondition: Definition ???
|
|
|
|
*/
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-12-17 00:33:02 +00:00
|
|
|
static int __maybe_unused arche_apb_ctrl_resume(struct device *dev)
|
2015-12-16 10:59:19 +00:00
|
|
|
{
|
|
|
|
/*
|
2022-04-13 04:38:51 +00:00
|
|
|
* At least for ES2 we have to meet the delay requirement between
|
2015-12-16 10:59:19 +00:00
|
|
|
* unipro switch and AP bridge init, depending on whether bridge is in
|
|
|
|
* OFF state or standby state.
|
|
|
|
*
|
|
|
|
* Based on whether bridge is in standby or OFF state we may have to
|
|
|
|
* assert multiple signals. Please refer to WDM spec, for more info.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-07-13 00:41:21 +00:00
|
|
|
static void arche_apb_ctrl_shutdown(struct platform_device *pdev)
|
|
|
|
{
|
|
|
|
apb_ctrl_poweroff(&pdev->dev);
|
|
|
|
}
|
|
|
|
|
2016-04-20 06:18:37 +00:00
|
|
|
static SIMPLE_DEV_PM_OPS(arche_apb_ctrl_pm_ops, arche_apb_ctrl_suspend,
|
|
|
|
arche_apb_ctrl_resume);
|
|
|
|
|
2016-09-22 15:33:33 +00:00
|
|
|
static const struct of_device_id arche_apb_ctrl_of_match[] = {
|
2016-04-20 06:18:37 +00:00
|
|
|
{ .compatible = "usbffff,2", },
|
|
|
|
{ },
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct platform_driver arche_apb_ctrl_device_driver = {
|
|
|
|
.probe = arche_apb_ctrl_probe,
|
2023-04-03 15:39:54 +00:00
|
|
|
.remove_new = arche_apb_ctrl_remove,
|
2016-07-13 00:41:21 +00:00
|
|
|
.shutdown = arche_apb_ctrl_shutdown,
|
2016-04-20 06:18:37 +00:00
|
|
|
.driver = {
|
|
|
|
.name = "arche-apb-ctrl",
|
|
|
|
.pm = &arche_apb_ctrl_pm_ops,
|
|
|
|
.of_match_table = arche_apb_ctrl_of_match,
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
int __init arche_apb_init(void)
|
|
|
|
{
|
|
|
|
return platform_driver_register(&arche_apb_ctrl_device_driver);
|
|
|
|
}
|
|
|
|
|
|
|
|
void __exit arche_apb_exit(void)
|
|
|
|
{
|
|
|
|
platform_driver_unregister(&arche_apb_ctrl_device_driver);
|
|
|
|
}
|