drm/radeon/kms: add ioport register access
This is required for the NB_MISC regs on rs780/rs880 which means HDMI/DVI/DP ports using PCIEPHY won't work without it. It might also help with s/r (asic init) issues on other atombios cards. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=28774 and similar issues reported by Alberto Milone. [airlied: Squash io fix patch] Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Tested-by: Rafał Miłecki <zajec5@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
fe50ac78a6
commit
351a52a241
|
@ -108,12 +108,11 @@ static uint32_t atom_iio_execute(struct atom_context *ctx, int base,
|
||||||
base++;
|
base++;
|
||||||
break;
|
break;
|
||||||
case ATOM_IIO_READ:
|
case ATOM_IIO_READ:
|
||||||
temp = ctx->card->reg_read(ctx->card, CU16(base + 1));
|
temp = ctx->card->ioreg_read(ctx->card, CU16(base + 1));
|
||||||
base += 3;
|
base += 3;
|
||||||
break;
|
break;
|
||||||
case ATOM_IIO_WRITE:
|
case ATOM_IIO_WRITE:
|
||||||
(void)ctx->card->reg_read(ctx->card, CU16(base + 1));
|
ctx->card->ioreg_write(ctx->card, CU16(base + 1), temp);
|
||||||
ctx->card->reg_write(ctx->card, CU16(base + 1), temp);
|
|
||||||
base += 3;
|
base += 3;
|
||||||
break;
|
break;
|
||||||
case ATOM_IIO_CLEAR:
|
case ATOM_IIO_CLEAR:
|
||||||
|
|
|
@ -113,6 +113,8 @@ struct card_info {
|
||||||
struct drm_device *dev;
|
struct drm_device *dev;
|
||||||
void (* reg_write)(struct card_info *, uint32_t, uint32_t); /* filled by driver */
|
void (* reg_write)(struct card_info *, uint32_t, uint32_t); /* filled by driver */
|
||||||
uint32_t (* reg_read)(struct card_info *, uint32_t); /* filled by driver */
|
uint32_t (* reg_read)(struct card_info *, uint32_t); /* filled by driver */
|
||||||
|
void (* ioreg_write)(struct card_info *, uint32_t, uint32_t); /* filled by driver */
|
||||||
|
uint32_t (* ioreg_read)(struct card_info *, uint32_t); /* filled by driver */
|
||||||
void (* mc_write)(struct card_info *, uint32_t, uint32_t); /* filled by driver */
|
void (* mc_write)(struct card_info *, uint32_t, uint32_t); /* filled by driver */
|
||||||
uint32_t (* mc_read)(struct card_info *, uint32_t); /* filled by driver */
|
uint32_t (* mc_read)(struct card_info *, uint32_t); /* filled by driver */
|
||||||
void (* pll_write)(struct card_info *, uint32_t, uint32_t); /* filled by driver */
|
void (* pll_write)(struct card_info *, uint32_t, uint32_t); /* filled by driver */
|
||||||
|
|
|
@ -1048,6 +1048,9 @@ struct radeon_device {
|
||||||
uint32_t pcie_reg_mask;
|
uint32_t pcie_reg_mask;
|
||||||
radeon_rreg_t pciep_rreg;
|
radeon_rreg_t pciep_rreg;
|
||||||
radeon_wreg_t pciep_wreg;
|
radeon_wreg_t pciep_wreg;
|
||||||
|
/* io port */
|
||||||
|
void __iomem *rio_mem;
|
||||||
|
resource_size_t rio_mem_size;
|
||||||
struct radeon_clock clock;
|
struct radeon_clock clock;
|
||||||
struct radeon_mc mc;
|
struct radeon_mc mc;
|
||||||
struct radeon_gart gart;
|
struct radeon_gart gart;
|
||||||
|
@ -1130,6 +1133,26 @@ static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline u32 r100_io_rreg(struct radeon_device *rdev, u32 reg)
|
||||||
|
{
|
||||||
|
if (reg < rdev->rio_mem_size)
|
||||||
|
return ioread32(rdev->rio_mem + reg);
|
||||||
|
else {
|
||||||
|
iowrite32(reg, rdev->rio_mem + RADEON_MM_INDEX);
|
||||||
|
return ioread32(rdev->rio_mem + RADEON_MM_DATA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v)
|
||||||
|
{
|
||||||
|
if (reg < rdev->rio_mem_size)
|
||||||
|
iowrite32(v, rdev->rio_mem + reg);
|
||||||
|
else {
|
||||||
|
iowrite32(reg, rdev->rio_mem + RADEON_MM_INDEX);
|
||||||
|
iowrite32(v, rdev->rio_mem + RADEON_MM_DATA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cast helper
|
* Cast helper
|
||||||
*/
|
*/
|
||||||
|
@ -1168,6 +1191,8 @@ static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32
|
||||||
WREG32_PLL(reg, tmp_); \
|
WREG32_PLL(reg, tmp_); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define DREG32_SYS(sqf, rdev, reg) seq_printf((sqf), #reg " : 0x%08X\n", r100_mm_rreg((rdev), (reg)))
|
#define DREG32_SYS(sqf, rdev, reg) seq_printf((sqf), #reg " : 0x%08X\n", r100_mm_rreg((rdev), (reg)))
|
||||||
|
#define RREG32_IO(reg) r100_io_rreg(rdev, (reg))
|
||||||
|
#define WREG32_IO(reg, v) r100_io_wreg(rdev, (reg), (v))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Indirect registers accessor
|
* Indirect registers accessor
|
||||||
|
|
|
@ -415,6 +415,22 @@ static uint32_t cail_reg_read(struct card_info *info, uint32_t reg)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val)
|
||||||
|
{
|
||||||
|
struct radeon_device *rdev = info->dev->dev_private;
|
||||||
|
|
||||||
|
WREG32_IO(reg*4, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg)
|
||||||
|
{
|
||||||
|
struct radeon_device *rdev = info->dev->dev_private;
|
||||||
|
uint32_t r;
|
||||||
|
|
||||||
|
r = RREG32_IO(reg*4);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
int radeon_atombios_init(struct radeon_device *rdev)
|
int radeon_atombios_init(struct radeon_device *rdev)
|
||||||
{
|
{
|
||||||
struct card_info *atom_card_info =
|
struct card_info *atom_card_info =
|
||||||
|
@ -427,6 +443,15 @@ int radeon_atombios_init(struct radeon_device *rdev)
|
||||||
atom_card_info->dev = rdev->ddev;
|
atom_card_info->dev = rdev->ddev;
|
||||||
atom_card_info->reg_read = cail_reg_read;
|
atom_card_info->reg_read = cail_reg_read;
|
||||||
atom_card_info->reg_write = cail_reg_write;
|
atom_card_info->reg_write = cail_reg_write;
|
||||||
|
/* needed for iio ops */
|
||||||
|
if (rdev->rio_mem) {
|
||||||
|
atom_card_info->ioreg_read = cail_ioreg_read;
|
||||||
|
atom_card_info->ioreg_write = cail_ioreg_write;
|
||||||
|
} else {
|
||||||
|
DRM_ERROR("Unable to find PCI I/O BAR; using MMIO for ATOM IIO\n");
|
||||||
|
atom_card_info->ioreg_read = cail_reg_read;
|
||||||
|
atom_card_info->ioreg_write = cail_reg_write;
|
||||||
|
}
|
||||||
atom_card_info->mc_read = cail_mc_read;
|
atom_card_info->mc_read = cail_mc_read;
|
||||||
atom_card_info->mc_write = cail_mc_write;
|
atom_card_info->mc_write = cail_mc_write;
|
||||||
atom_card_info->pll_read = cail_pll_read;
|
atom_card_info->pll_read = cail_pll_read;
|
||||||
|
@ -573,7 +598,7 @@ int radeon_device_init(struct radeon_device *rdev,
|
||||||
struct pci_dev *pdev,
|
struct pci_dev *pdev,
|
||||||
uint32_t flags)
|
uint32_t flags)
|
||||||
{
|
{
|
||||||
int r;
|
int r, i;
|
||||||
int dma_bits;
|
int dma_bits;
|
||||||
|
|
||||||
rdev->shutdown = false;
|
rdev->shutdown = false;
|
||||||
|
@ -659,6 +684,17 @@ int radeon_device_init(struct radeon_device *rdev,
|
||||||
DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)rdev->rmmio_base);
|
DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)rdev->rmmio_base);
|
||||||
DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size);
|
DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size);
|
||||||
|
|
||||||
|
/* io port mapping */
|
||||||
|
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
|
||||||
|
if (pci_resource_flags(rdev->pdev, i) & IORESOURCE_IO) {
|
||||||
|
rdev->rio_mem_size = pci_resource_len(rdev->pdev, i);
|
||||||
|
rdev->rio_mem = pci_iomap(rdev->pdev, i, rdev->rio_mem_size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rdev->rio_mem == NULL)
|
||||||
|
DRM_ERROR("Unable to find PCI I/O BAR\n");
|
||||||
|
|
||||||
/* if we have > 1 VGA cards, then disable the radeon VGA resources */
|
/* if we have > 1 VGA cards, then disable the radeon VGA resources */
|
||||||
/* this will fail for cards that aren't VGA class devices, just
|
/* this will fail for cards that aren't VGA class devices, just
|
||||||
* ignore it */
|
* ignore it */
|
||||||
|
@ -701,6 +737,8 @@ void radeon_device_fini(struct radeon_device *rdev)
|
||||||
destroy_workqueue(rdev->wq);
|
destroy_workqueue(rdev->wq);
|
||||||
vga_switcheroo_unregister_client(rdev->pdev);
|
vga_switcheroo_unregister_client(rdev->pdev);
|
||||||
vga_client_register(rdev->pdev, NULL, NULL, NULL);
|
vga_client_register(rdev->pdev, NULL, NULL, NULL);
|
||||||
|
pci_iounmap(rdev->pdev, rdev->rio_mem);
|
||||||
|
rdev->rio_mem = NULL;
|
||||||
iounmap(rdev->rmmio);
|
iounmap(rdev->rmmio);
|
||||||
rdev->rmmio = NULL;
|
rdev->rmmio = NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue