uboot/arch/x86/cpu/broadwell/iobp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2016 Google, Inc
   4 *
   5 * Modified from coreboot
   6 */
   7
   8#include <common.h>
   9#include <errno.h>
  10#include <asm/intel_regs.h>
  11#include <asm/io.h>
  12#include <asm/arch/pch.h>
  13
  14#define IOBP_RETRY 1000
  15
  16/* IO Buffer Programming */
  17#define IOBPIRI         0x2330
  18#define IOBPD           0x2334
  19#define IOBPS           0x2338
  20#define  IOBPS_READY    0x0001
  21#define  IOBPS_TX_MASK  0x0006
  22#define  IOBPS_MASK     0xff00
  23#define  IOBPS_READ     0x0600
  24#define  IOBPS_WRITE    0x0700
  25#define IOBPU           0x233a
  26#define  IOBPU_MAGIC    0xf000
  27#define  IOBP_PCICFG_READ       0x0400
  28#define  IOBP_PCICFG_WRITE      0x0500
  29
  30static inline int iobp_poll(void)
  31{
  32        unsigned try;
  33
  34        for (try = IOBP_RETRY; try > 0; try--) {
  35                u16 status = readw(RCB_REG(IOBPS));
  36                if ((status & IOBPS_READY) == 0)
  37                        return 1;
  38                udelay(10);
  39        }
  40
  41        printf("IOBP: timeout waiting for transaction to complete\n");
  42        return 0;
  43}
  44
  45int pch_iobp_trans_start(u32 address, int op)
  46{
  47        if (!iobp_poll())
  48                return 0;
  49
  50        /* Set the address */
  51        writel(address, RCB_REG(IOBPIRI));
  52
  53        /* READ OPCODE */
  54        clrsetbits_le16(RCB_REG(IOBPS), IOBPS_MASK, op);
  55
  56        return 1;
  57}
  58
  59int pch_iobp_trans_finish(void)
  60{
  61        u16 status;
  62
  63        /* Undocumented magic */
  64        writew(IOBPU_MAGIC, RCB_REG(IOBPU));
  65
  66        /* Set ready bit */
  67        setbits_le16(RCB_REG(IOBPS), IOBPS_READY);
  68
  69        if (!iobp_poll())
  70                return 1;
  71
  72        /* Check for successful transaction */
  73        status = readw(RCB_REG(IOBPS));
  74        if (status & IOBPS_TX_MASK)
  75                return 1;
  76
  77        return 0;
  78}
  79
  80u32 pch_iobp_read(u32 address)
  81{
  82        if (!pch_iobp_trans_start(address, IOBPS_READ))
  83                return 0;
  84        if (pch_iobp_trans_finish()) {
  85                printf("IOBP: read 0x%08x failed\n", address);
  86                return 0;
  87        }
  88
  89        /* Read IOBP data */
  90        return readl(RCB_REG(IOBPD));
  91}
  92
  93int pch_iobp_write(u32 address, u32 data)
  94{
  95        if (!pch_iobp_trans_start(address, IOBPS_WRITE))
  96                return -EIO;
  97
  98        writel(data, RCB_REG(IOBPD));
  99
 100        if (pch_iobp_trans_finish()) {
 101                printf("IOBP: write 0x%08x failed\n", address);
 102                return -EIO;
 103        }
 104
 105        return 0;
 106}
 107
 108int pch_iobp_update(u32 address, u32 andvalue, u32 orvalue)
 109{
 110        u32 data = pch_iobp_read(address);
 111
 112        /* Update the data */
 113        data &= andvalue;
 114        data |= orvalue;
 115
 116        return pch_iobp_write(address, data);
 117}
 118
 119int pch_iobp_exec(u32 addr, u16 op_code, u8 route_id, u32 *data, u8 *resp)
 120{
 121        if (!data || !resp)
 122                return 0;
 123
 124        *resp = -1;
 125        if (!iobp_poll())
 126                return -EIO;
 127
 128        writel(addr, RCB_REG(IOBPIRI));
 129        clrsetbits_le16(RCB_REG(IOBPS), 0xff00, op_code);
 130        writew(IOBPU_MAGIC | route_id, RCB_REG(IOBPU));
 131
 132        writel(*data, RCB_REG(IOBPD));
 133        /* Set IOBPS[0] to trigger IOBP transaction*/
 134        setbits_le16(RCB_REG(IOBPS), 1);
 135
 136        if (!iobp_poll())
 137                return -EIO;
 138
 139        *resp = (readw(RCB_REG(IOBPS)) & IOBPS_TX_MASK) >> 1;
 140        *data = readl(RCB_REG(IOBPD));
 141
 142        return 0;
 143}
 144