Skip to content

Commit

Permalink
Merge tag 'asahi-soc-rtkit-pmgr-6.3' of https://github.com/AsahiLinux…
Browse files Browse the repository at this point in the history
…/linux into soc/drivers

Apple SoC RTKit/PMGR updates for 6.3.

This time around we have a PMGR change to allow IRQ-safe usage, RTKit
crash register dump decoding, and a bunch of RTKit API changes used by
upcoming drivers.

* tag 'asahi-soc-rtkit-pmgr-6.3' of https://github.com/AsahiLinux/linux:
  soc: apple: rtkit: Add register dump decoding to crashlog
  soc: apple: rtkit: Export non-devm init/free functions
  soc: apple: rtkit: Add a private pointer to apple_rtkit_shmem
  soc: apple: apple-pmgr-pwrstate: Switch to IRQ-safe mode
  soc: apple: rtkit: Add apple_rtkit_idle() function

Link: https://lore.kernel.org/r/4790bdc4-b6e2-228b-771f-023363f65fb3@marcan.st
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
  • Loading branch information
Arnd Bergmann committed Feb 6, 2023
2 parents e26f841 + 22991d8 commit 7d47f6f
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 9 deletions.
11 changes: 7 additions & 4 deletions drivers/soc/apple/apple-pmgr-pwrstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ static int apple_pmgr_ps_power_off(struct generic_pm_domain *genpd)
static int apple_pmgr_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
{
struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev);
unsigned long flags;

mutex_lock(&ps->genpd.mlock);
spin_lock_irqsave(&ps->genpd.slock, flags);

if (ps->genpd.status == GENPD_STATE_OFF)
dev_err(ps->dev, "PS 0x%x: asserting RESET while powered down\n", ps->offset);
Expand All @@ -129,16 +130,17 @@ static int apple_pmgr_reset_assert(struct reset_controller_dev *rcdev, unsigned
regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_RESET,
APPLE_PMGR_RESET);

mutex_unlock(&ps->genpd.mlock);
spin_unlock_irqrestore(&ps->genpd.slock, flags);

return 0;
}

static int apple_pmgr_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
{
struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev);
unsigned long flags;

mutex_lock(&ps->genpd.mlock);
spin_lock_irqsave(&ps->genpd.slock, flags);

dev_dbg(ps->dev, "PS 0x%x: deassert reset\n", ps->offset);
regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_RESET, 0);
Expand All @@ -147,7 +149,7 @@ static int apple_pmgr_reset_deassert(struct reset_controller_dev *rcdev, unsigne
if (ps->genpd.status == GENPD_STATE_OFF)
dev_err(ps->dev, "PS 0x%x: RESET was deasserted while powered down\n", ps->offset);

mutex_unlock(&ps->genpd.mlock);
spin_unlock_irqrestore(&ps->genpd.slock, flags);

return 0;
}
Expand Down Expand Up @@ -222,6 +224,7 @@ static int apple_pmgr_ps_probe(struct platform_device *pdev)
return ret;
}

ps->genpd.flags |= GENPD_FLAG_IRQ_SAFE;
ps->genpd.name = name;
ps->genpd.power_on = apple_pmgr_ps_power_on;
ps->genpd.power_off = apple_pmgr_ps_power_off;
Expand Down
93 changes: 93 additions & 0 deletions drivers/soc/apple/rtkit-crashlog.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@
#define APPLE_RTKIT_CRASHLOG_VERSION FOURCC('C', 'v', 'e', 'r')
#define APPLE_RTKIT_CRASHLOG_MBOX FOURCC('C', 'm', 'b', 'x')
#define APPLE_RTKIT_CRASHLOG_TIME FOURCC('C', 't', 'i', 'm')
#define APPLE_RTKIT_CRASHLOG_REGS FOURCC('C', 'r', 'g', '8')

/* For COMPILE_TEST on non-ARM64 architectures */
#ifndef PSR_MODE_EL0t
#define PSR_MODE_EL0t 0x00000000
#define PSR_MODE_EL1t 0x00000004
#define PSR_MODE_EL1h 0x00000005
#define PSR_MODE_EL2t 0x00000008
#define PSR_MODE_EL2h 0x00000009
#define PSR_MODE_MASK 0x0000000f
#endif

struct apple_rtkit_crashlog_header {
u32 fourcc;
Expand All @@ -31,6 +42,24 @@ struct apple_rtkit_crashlog_mbox_entry {
};
static_assert(sizeof(struct apple_rtkit_crashlog_mbox_entry) == 0x18);

struct apple_rtkit_crashlog_regs {
u32 unk_0;
u32 unk_4;
u64 regs[31];
u64 sp;
u64 pc;
u64 psr;
u64 cpacr;
u64 fpsr;
u64 fpcr;
u64 unk[64];
u64 far;
u64 unk_X;
u64 esr;
u64 unk_Z;
};
static_assert(sizeof(struct apple_rtkit_crashlog_regs) == 0x350);

static void apple_rtkit_crashlog_dump_str(struct apple_rtkit *rtk, u8 *bfr,
size_t size)
{
Expand Down Expand Up @@ -94,6 +123,66 @@ static void apple_rtkit_crashlog_dump_mailbox(struct apple_rtkit *rtk, u8 *bfr,
}
}

static void apple_rtkit_crashlog_dump_regs(struct apple_rtkit *rtk, u8 *bfr,
size_t size)
{
struct apple_rtkit_crashlog_regs regs;
const char *el;
int i;

if (size < sizeof(regs)) {
dev_warn(rtk->dev, "RTKit: Regs section too small: 0x%zx", size);
return;
}

memcpy(&regs, bfr, sizeof(regs));

switch (regs.psr & PSR_MODE_MASK) {
case PSR_MODE_EL0t:
el = "EL0t";
break;
case PSR_MODE_EL1t:
el = "EL1t";
break;
case PSR_MODE_EL1h:
el = "EL1h";
break;
case PSR_MODE_EL2t:
el = "EL2t";
break;
case PSR_MODE_EL2h:
el = "EL2h";
break;
default:
el = "unknown";
break;
}

dev_warn(rtk->dev, "RTKit: Exception dump:");
dev_warn(rtk->dev, " == Exception taken from %s ==", el);
dev_warn(rtk->dev, " PSR = 0x%llx", regs.psr);
dev_warn(rtk->dev, " PC = 0x%llx\n", regs.pc);
dev_warn(rtk->dev, " ESR = 0x%llx\n", regs.esr);
dev_warn(rtk->dev, " FAR = 0x%llx\n", regs.far);
dev_warn(rtk->dev, " SP = 0x%llx\n", regs.sp);
dev_warn(rtk->dev, "\n");

for (i = 0; i < 31; i += 4) {
if (i < 28)
dev_warn(rtk->dev,
" x%02d-x%02d = %016llx %016llx %016llx %016llx\n",
i, i + 3,
regs.regs[i], regs.regs[i + 1],
regs.regs[i + 2], regs.regs[i + 3]);
else
dev_warn(rtk->dev,
" x%02d-x%02d = %016llx %016llx %016llx\n", i, i + 3,
regs.regs[i], regs.regs[i + 1], regs.regs[i + 2]);
}

dev_warn(rtk->dev, "\n");
}

void apple_rtkit_crashlog_dump(struct apple_rtkit *rtk, u8 *bfr, size_t size)
{
size_t offset;
Expand Down Expand Up @@ -140,6 +229,10 @@ void apple_rtkit_crashlog_dump(struct apple_rtkit *rtk, u8 *bfr, size_t size)
apple_rtkit_crashlog_dump_time(rtk, bfr + offset + 16,
section_size);
break;
case APPLE_RTKIT_CRASHLOG_REGS:
apple_rtkit_crashlog_dump_regs(rtk, bfr + offset + 16,
section_size);
break;
default:
dev_warn(rtk->dev,
"RTKit: Unknown crashlog section: %x",
Expand Down
36 changes: 31 additions & 5 deletions drivers/soc/apple/rtkit.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
enum {
APPLE_RTKIT_PWR_STATE_OFF = 0x00, /* power off, cannot be restarted */
APPLE_RTKIT_PWR_STATE_SLEEP = 0x01, /* sleeping, can be restarted */
APPLE_RTKIT_PWR_STATE_IDLE = 0x201, /* sleeping, retain state */
APPLE_RTKIT_PWR_STATE_QUIESCED = 0x10, /* running but no communication */
APPLE_RTKIT_PWR_STATE_ON = 0x20, /* normal operating state */
};
Expand Down Expand Up @@ -698,7 +699,7 @@ static int apple_rtkit_request_mbox_chan(struct apple_rtkit *rtk)
return 0;
}

static struct apple_rtkit *apple_rtkit_init(struct device *dev, void *cookie,
struct apple_rtkit *apple_rtkit_init(struct device *dev, void *cookie,
const char *mbox_name, int mbox_idx,
const struct apple_rtkit_ops *ops)
{
Expand Down Expand Up @@ -750,6 +751,7 @@ static struct apple_rtkit *apple_rtkit_init(struct device *dev, void *cookie,
kfree(rtk);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(apple_rtkit_init);

static int apple_rtkit_wait_for_completion(struct completion *c)
{
Expand Down Expand Up @@ -881,6 +883,26 @@ int apple_rtkit_shutdown(struct apple_rtkit *rtk)
}
EXPORT_SYMBOL_GPL(apple_rtkit_shutdown);

int apple_rtkit_idle(struct apple_rtkit *rtk)
{
int ret;

/* if OFF is used here the co-processor will not wake up again */
ret = apple_rtkit_set_ap_power_state(rtk,
APPLE_RTKIT_PWR_STATE_IDLE);
if (ret)
return ret;

ret = apple_rtkit_set_iop_power_state(rtk, APPLE_RTKIT_PWR_STATE_IDLE);
if (ret)
return ret;

rtk->iop_power_state = APPLE_RTKIT_PWR_STATE_IDLE;
rtk->ap_power_state = APPLE_RTKIT_PWR_STATE_IDLE;
return 0;
}
EXPORT_SYMBOL_GPL(apple_rtkit_idle);

int apple_rtkit_quiesce(struct apple_rtkit *rtk)
{
int ret;
Expand Down Expand Up @@ -926,10 +948,8 @@ int apple_rtkit_wake(struct apple_rtkit *rtk)
}
EXPORT_SYMBOL_GPL(apple_rtkit_wake);

static void apple_rtkit_free(void *data)
void apple_rtkit_free(struct apple_rtkit *rtk)
{
struct apple_rtkit *rtk = data;

mbox_free_channel(rtk->mbox_chan);
destroy_workqueue(rtk->wq);

Expand All @@ -940,6 +960,12 @@ static void apple_rtkit_free(void *data)
kfree(rtk->syslog_msg_buffer);
kfree(rtk);
}
EXPORT_SYMBOL_GPL(apple_rtkit_free);

static void apple_rtkit_free_wrapper(void *data)
{
apple_rtkit_free(data);
}

struct apple_rtkit *devm_apple_rtkit_init(struct device *dev, void *cookie,
const char *mbox_name, int mbox_idx,
Expand All @@ -952,7 +978,7 @@ struct apple_rtkit *devm_apple_rtkit_init(struct device *dev, void *cookie,
if (IS_ERR(rtk))
return rtk;

ret = devm_add_action_or_reset(dev, apple_rtkit_free, rtk);
ret = devm_add_action_or_reset(dev, apple_rtkit_free_wrapper, rtk);
if (ret)
return ERR_PTR(ret);

Expand Down
26 changes: 26 additions & 0 deletions include/linux/soc/apple/rtkit.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* @size: Size of the shared memory buffer.
* @iova: Device VA of shared memory buffer.
* @is_mapped: Shared memory buffer is managed by the co-processor.
* @private: Private data pointer for the parent driver.
*/

struct apple_rtkit_shmem {
Expand All @@ -30,6 +31,7 @@ struct apple_rtkit_shmem {
size_t size;
dma_addr_t iova;
bool is_mapped;
void *private;
};

/*
Expand Down Expand Up @@ -77,6 +79,25 @@ struct apple_rtkit *devm_apple_rtkit_init(struct device *dev, void *cookie,
const char *mbox_name, int mbox_idx,
const struct apple_rtkit_ops *ops);

/*
* Non-devm version of devm_apple_rtkit_init. Must be freed with
* apple_rtkit_free.
*
* @dev: Pointer to the device node this coprocessor is assocated with
* @cookie: opaque cookie passed to all functions defined in rtkit_ops
* @mbox_name: mailbox name used to communicate with the co-processor
* @mbox_idx: mailbox index to be used if mbox_name is NULL
* @ops: pointer to rtkit_ops to be used for this co-processor
*/
struct apple_rtkit *apple_rtkit_init(struct device *dev, void *cookie,
const char *mbox_name, int mbox_idx,
const struct apple_rtkit_ops *ops);

/*
* Free an instance of apple_rtkit.
*/
void apple_rtkit_free(struct apple_rtkit *rtk);

/*
* Reinitialize internal structures. Must only be called with the co-processor
* is held in reset.
Expand Down Expand Up @@ -104,6 +125,11 @@ int apple_rtkit_wake(struct apple_rtkit *rtk);
*/
int apple_rtkit_shutdown(struct apple_rtkit *rtk);

/*
* Put the co-processor into idle mode
*/
int apple_rtkit_idle(struct apple_rtkit *rtk);

/*
* Checks if RTKit is running and ready to handle messages.
*/
Expand Down

0 comments on commit 7d47f6f

Please sign in to comment.